01背包问题(回溯法实现,java)


上两天学习的回溯算法,老师让我们回溯法来解决01背包问题,

经过了几天的改改增增,终于实现成功了。

自我感觉回溯算法思想,从左到右,一步一步,能走则走,不能则过!

下面直接贴代码,代码上详细注释!

import java.util.Arrays;

/**
 * 回溯法的01背包
 * 
 * @author anLA
 *
 */
public class BagFBack {

	private MyElement[] myelements; // 封装的物品
	private float s; // 背包容量
	private float nowWeight = 0; // 记录当前以拿重量
	private float nowPrice = 0; // 记录当前以拿价格
	private float betterValue; // 记录最多的价格

	/*
	 * 构造方法,用于初始化各个变量
	 */
	public BagFBack(float[] w, float[] v, float s) {
		myelements = new MyElement[w.length];
		for (int i = 0; i < w.length; i++) {
			myelements[i] = new MyElement();
			myelements[i].v = v[i];
			myelements[i].w = w[i];

		}
		this.s = s;
		// 对数组进行价值排序,系统的是从小到大的,但我讲MyElement改了,使得是从大到小
		Arrays.sort(myelements);
		System.out.println("物品价值" + "	" + "物品重量");
		for (int i = 0; i < myelements.length; i++) {
			System.out.print(myelements[i].v + "	" + myelements[i].w);
			System.out.println();

		}

	}

	public void traceBack(int t) {
		if (t >= myelements.length) {
			// 已经遍历到最下一层,也就是最后一个
			System.out.println("找到方法");
			betterValue = nowPrice;
			System.out.println("最终拿到: " + betterValue);
			output(myelements);
			return;
		}
		// 首先进入走左子树
		if (nowWeight + myelements[t].w < s) {
			// 进入左子树
			nowWeight += myelements[t].w;
			nowPrice += myelements[t].v;
			myelements[t].take = true;
			traceBack(t + 1);
			// 还原现场
			nowWeight -= myelements[t].w;
			nowPrice -= myelements[t].v;
			myelements[t].take = false;
		}

		// 进入右子树,以及要进入的条件
		if (bound(t + 1) > betterValue) {
			traceBack(t + 1);
		}

	}

	// 输出方法,用于输出
	public void output(MyElement[] myelements2) {
		System.out.print("拿重量为这些的物品:");
		for (int i = 0; i < myelements2.length; i++) {
			if (myelements2[i].take) {
				System.out.print(myelements2[i].w + "	");
			}

		}
	}

	/**
	 * 用于计算右边的,如果右边大些,就直接进入
	 * 
	 * @param i
	 * @return
	 */
	public float bound(int i) {
		// 计算上界
		float cleft = s - nowWeight;
		float bound = nowPrice;
		// 以物品单位价值递减顺序装入物品
		while (i < myelements.length && cleft > myelements[i].v) {
			cleft -= myelements[i].w;
			bound += myelements[i].v;
			i++;
			myelements[i].take = true;
		}

		// // 如果最后一个不能整个放下去,那就装满背包,此问题讨论01背包,要么装,要么不装,所以不用加这一句
		// if (i < myelements.length) {
		// bound += (myelements[i].v / myelements[i].w) * cleft;
		// }
		return bound;

	}

	/**
	 * 封装为物品的类
	 * 
	 * @author anLA
	 *
	 */
	class MyElement implements Comparable {
		float w;
		float v;
		boolean take = false;

		// 更改实现的方法,方便调用系统函数
		@Override
		public int compareTo(Object o) {
			if (v / w < ((MyElement) o).v / ((MyElement) o).w) {
				return 1; // 注意,此处主要用于排序,从大到小排序,所以故意反
			} else {
				return -1;
			}
		}
	}

	public static void main(String[] args) {

		float[] w = { 3.4f, 2.5f, 6f, 4f, 9.0f };
		float[] v = { 3f, 2.5f, 5f, 9f, 6.2f };
		float s = 10;
		BagFBack bagFBack = new BagFBack(w, v, s);
		// 从第0层开始回溯
		bagFBack.traceBack(0);
	}

}


  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值