---装载问题 ——回溯法
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.回溯法联系的例子太少了