动态规划法解0-1背包问题

0-1背包问题:有一个贼在偷窃一家商店时,发现有n件物品,第i件物品价值vi,重wi。他希望带走的东西越值钱越好,但他的背包中至多只能装下C的东西。应该带走哪几样东西,使得装入背包的物品价值最大?这个问题之所以称为0-1背包,是因为每件物品或被带走;或被留下;小偷不能只带走某个物品的一部分或带走同一物品两次。

动态规划法解题的步骤:

1. 找出最优解的性质;

2. 递归地定义最优值;

3. 以自底向上的方式计算最优值;

4. 根据计算最优值过程中得到的信息,构造最优解;

package ch03.book;

/**
 * Resolve 0-1 backpack problem using dynamic planning 
 * @author wanyongquan
 * 
 */
public class Backpack {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] weight = {35, 30, 60, 50, 40, 10, 25};
		int[] profit = {10, 40, 30, 50, 35, 40, 30};
		int[][] maxProfit = new int[weight.length][151];
		backpack(profit, weight, 150, maxProfit);
		int[] solution = new int[weight.length];
		trackback(maxProfit, weight, 150, solution);
		
		// 
		for(int i=0;i<solution.length; i++) {
			System.out.printf("%4d", solution[i]);
		}
		System.out.printf("\r\nmax proft: %d", maxProfit[0][150]);
	}

	public static void backpack(int[] value, int[] weight, int capacity, int [][] m) {
		
		int n = value.length -1;
		int jMax = Math.min(weight[n] - 1, capacity);
		//先计算 i= n 时的最优值;
		for(int j=0; j<jMax; j++)
		{
			m[n][j] = 0;
		}
		for(int j= weight[n];j<= capacity; j++) {
			m[n][j] = value[n];
		}
		// 接着,根据动态规划的最优值的递归定义,m[i][j] 表示背包容量为j,可选择物品为i, i+1,...,n时,0-1背包问题的最优值。
		// 利用递归定义,以自底(i=n-1)向上(i=0)的方式计算最优值;		
		for(int i=n-1; i>0; i--) {
			jMax = Math.min(weight[i] -1, capacity);
			for(int j= 0; j<jMax ; j++) {
				m[i][j] = m[i+1][j];
			}
			for(int j= weight[i]; j<=capacity; j++) {
				m[i][j] = Math.max(m[i+1][j], m[i+1][j-weight[i]] + value[i]);
			}
		}
		// 利用递归式计算i=0时的最优值;
		if(capacity>= weight[0]) {
			m[0][capacity] = Math.max(m[1][capacity], m[1][capacity-weight[0]] + value[0]);
		}
		else{
			m[0][capacity] = m[1][capacity];
		}
	}
   /**
    * 根据backpack算法计算后得到的信息,计算出最优解;
    */
	public static void trackback(int[][]m , int[] weight, int capacity, int [] solution) {
		int n = weight.length-1;
		for(int i = 0; i<n;i++) {
			if (m[i][capacity] == m[i+1][capacity]) {
				solution[i] = 0; // item i not been put in backpack;
			}
			else {
				solution[i] = 1;
				capacity -= weight[i];
			}
		}
		solution[n] = m[n][capacity] > 0? 1:0;
		
	}
}

运行结果: 

  solution:

1   1   0   1   0   1   1

max proft: 170

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

曼车斯基

如果内容对你有用,赏杯咖啡吧!

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

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

打赏作者

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

抵扣说明:

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

余额充值