---裝載問題 ——回溯法
tags: 回溯法
grammar_cjkRuby: true
一 問題描述
二 問題分析
1. 解空間為子集樹
2.可以設置減枝函數
具體設計為:設置右子樹上界函數
三 代碼設計
package backtracking_loading;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;
public class bin {
public static void main(String[] args) throws IOException {
int []w={0,20,10,40,30,50,60,70};
int c=180;
loading myLoading=new loading(c, w);
}
}
class loading {
int c; //第一艘船的載重量
int []w; //集裝箱數組
int cw; //當前載重量
int bestw; //動態最優解
int n; //集裝箱個數
int []cx; //記錄遞歸路徑
int []x; //最優遞歸路勁
int rw; //剩余重量
public loading(int c,int []w) throws IOException {
this.c=c;
this.w=w;
this.cw=0;
this.bestw=0;
this.n=w.length-1;
this.x=new int[w.length]; //記錄遞歸最優路徑
this.cx=new int[w.length]; //記錄遞歸當前路勁
this.rw=0;
for(int i=1; i<w.length; i++)
{
rw+=w[i];
}
Loading(1);
display();
}
public void Loading(int i) {
//遞歸出口
if(i>n) //遍歷完一個分支
{
if(cw>bestw)
{
//更新最優解
bestw=cw;
x=Arrays.copyOf(cx,cx.length);
}
return;
}
//減枝函數
rw-=w[i]; //剩余重量,不考慮第i個集裝箱
//左子樹 1
if(cw+w[i]<=c)
{
cw+=w[i];
cx[i]=1; //裝入
Loading(i+1);
cw-=w[i]; //回溯,相當關鍵
}
if(cw+rw>bestw)
{
//右子樹 0
cx[i]=0; //不裝入
Loading(i+1);
}
rw+=w[i]; //結點回溯
}
public void display() throws IOException {
BufferedWriter fout=new BufferedWriter(new FileWriter("out.txt"));
fout.write("c="+c);
fout.newLine();
fout.write("bestw="+bestw);
fout.newLine();
fout.write("x[i]:");
fout.newLine();
for(int i=1; i<x.length; i++)
{
fout.write("x["+i+"]="+x[i]);
fout.newLine();
}
fout.flush();
}
}
四 運行結果
五 總結收獲
- 熟悉回溯法
六 不足
1.回溯法聯系的例子太少了