回溯法最优装载问题(Java实现)

最优装载问题

问题描述

  • 有一批共n个集装箱要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量为wi,装载问题要求确定是否有一个合理的装载方案可将这些集装箱装上这2艘轮船。如果有,找出一种装载方案。例如:当n=3,c1=c2=50,且w=[10,40,40]时,则可以将集装箱1和2装到第一艘轮船上

Java源代码

注释很详细

 /*
 * 若尘
 */
package loading2;

/**
 * 装载问题
 * @author ruochen
 * @version 1.0
 */
public class Loading {
	/** 集装箱数 */
	static int n;
	/** 集装箱重量数组 */
	static int[] w;
	/** 第一艘轮船的载重量 */
	static int c1;
	/** 第二艘轮船的载重量 */
	static int c2;
	/** 当前载重量 */
	static int cw;
	/** 当前最优载重量 */
	static int bestw;
	/** 剩余集装箱重量 */
	static int r;
	/** 当前解 */
	static int[] x;
	/** 当前最优解 */
	static int[] bestx;

	public static void main(String[] args) {
		// 下标从1开始,所以第一个元素为0
		int[] ww = {0, 10, 40, 40};
		int cc1 = 50;
		int cc2 = 50;
		System.out.println(maxLoading(ww, cc1, cc2));
		outPut();
	}
	
	/** 返回不超过c 的最大子集和 */
	public static int maxLoading(int[] ww, int cc1, int cc2) {
		n = ww.length - 1;
		w = ww;
		c1 = cc1;
		c2 = cc2;
		cw = 0;
		bestw = 0;
		x = new int[n + 1];
		bestx = new int[n + 1];
		r = 0;
		// r 初始值为全部集装箱总重
		for (int i= 1; i <= n; i++) {
			r += w[i];
		}
		// 计算最优载重量
		backTrack(1);
		return bestw;
	}

	/** 回溯算法 */
	public static void backTrack(int i) {
		// 搜索第 i 层节点
		if (i > n) {
			// 到达叶节点
			if (cw > bestw) {
				for (int j = 1; j <= n; j++) {
					bestx[j] = x[j];
				}
				bestw = cw;
			}
			return ;
		}
		// 搜索子树
		r -= w[i];
		if (cw + w[i] <= c1) {
			// 重量不超过 c
			// 搜索左子树
			x[i] = 1;
			cw += w[i];
			backTrack(i + 1);
			// 还原
			x[i] = 1;
			cw -= w[i];
		}
		// 只在右子树进行上界函数判断是因为其对左子树无影响
		// 左子树是选择放,上界函数 = cw(当前重量) + r(剩余重量)
		if (cw + r > bestw) {
			x[i] = 0;
			// 搜素右子树
			backTrack(i + 1);
		}
		r += w[i];
	}
	
	static void outPut() {
		int weight = 0;
		for (int i = 1; i <= n; i++) {
			if (bestx[i] == 0) {
				// 第一艘轮船装完后的剩余重量
				weight += w[i];
			}
		}
		if (weight > c2) {
			System.out.println("不能装入 ");
		} else {
			System.out.print("轮船一装入的货物为: ");
			for (int i = 1; i <= n; i++) {
				if (bestx[i] == 1) {
					System.out.print(i + " ");
				}
			}
			System.out.println();
			System.out.print("轮船二装入的货物为: ");
			for (int i = 1; i <= n; i++) {
				if (bestx[i] != 1) {
					System.out.print(i + " ");
				}
			}
		}
	}

}
50
轮船一装入的货物为: 1 2 
轮船二装入的货物为: 3 
  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值