回溯法经典例题(二):java解装载问题

装载问题

问题描述

  • 有一批共n个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集装箱i的重量为wi,且∑wi≤C1+C2,装载问题要求确定一个合理的装载方案可将这n个集装箱装上这2艘轮船。
  • 容易证明,如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案:
    (1) 首先将第一艘轮船尽可能装满;
    (2) 将剩余的集装箱装上第二艘轮船。

证明过程:
假设wt是已经装上第一艘轮船的集装箱重量和,由于题目要求,则需所有集装箱的重量减去wt得小于或等于第二艘轮船的最大载重量,又由于第二艘轮船的最大载重量和总集装箱重量为固定值,则wt需尽可能地大才能满足该要求。

定义解空间

将第一艘轮船尽可能装满等价于选取全体集装箱的一个子集,使该子集中集装箱重量之和最接近C1,该子集就是装载问题的解空间

确定解空间结构

由上可见,装载问题是特殊的01背包问题(不用考虑物品价值、仅考虑重量)
因此解空间结构同样是子集树
在这里插入图片描述

剪枝函数

在这里插入图片描述

代码实现

public class clproblem {
	static int n;//集装箱数
	static int[] w;//集装箱重量数组
	static int c;//第一艘轮船的载重量
	
	static int cw;//当前载重量
	static int bw;//当前最优载重量
	
	static int r;//岸上可供选择的集装箱总重量
	
	static int[]x;//当前解
	static int[]bx;//当前最优解
	
	public static void init(int num,int[] ww,int cc) {
		//初始化类数据成员
		n=num;
		w=ww;
		c=cc;
		cw=0;
		bw=0;
		x=new int[n+1];
		bx=x;
		for(int i=0;i<n;i++)
			r+=w[i];//初始化
		backtrack(1);
	}
	
	public static void backtrack(int t) {
		//搜索第i层结点
		if(t>n) {//到达叶结点
			for(int j=1;j<=n;j++)
				bx[j]=x[j];
			bw=cw;
			return;
		}
		//搜索子树
		r-=w[t-1];//岸上剩余可选择集装箱总重量
		if(cw+w[t-1]<=c) {
			//搜索左子树
			x[t-1]=1;	
			cw+=w[t-1];
			backtrack(t+1);//向下搜索
			cw-=w[t-1];//回到当前可扩展结点需要减掉往下时加的重量
		}
		if(cw+r>bw) {
			//搜索右子树,右子树都是不放入,因此默认右子树都可达
			x[t-1]=0;
			backtrack(t+1);
		}
		r+=w[t-1];//返回当前可扩展结点需要加上可选择集装箱重量
	}
	
	public static void main(String[] args) {
		System.out.println("请输入集装箱个数:");
		Scanner sc=new Scanner(System.in);
		int num=sc.nextInt();
		int[]ww=new int[num];
		System.out.println("请输入各个集装箱的重量:");
		for(int i=0;i<num;i++)
			ww[i]=sc.nextInt();
		System.out.println("请输入第一艘轮船的最大承载重量:");
		int cc=sc.nextInt();
		init(num,ww,cc);
		System.out.print("此时最优解为:\n{");
		for(int i=0;i<num;i++) {
			if(i==num-1)
				System.out.println(bx[i]+"}");
			else
				System.out.print(bx[i]+",");
		}
		System.out.println("最优载重量为:\n"+bw);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值