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

问题:购物车体积为13,求能选择的最大价值
在这里插入图片描述

P[i,c]:i代表i商品,c代表剩余体积
Vi:第i个商品的体积,Pi:第i个商品的价格

P[i,c]=max{p[i-1,c-vi]+pi,p[i-1,c]}
即:比较选i时的价值(p[i-1,c-vi]+pi)和不选i时的价值(p[i-1,c])的大小,选择价值最大的

首先初始化当i=0时或c=0时P[i,c]都为0
在这里插入图片描述

最后一个点就是最优解
在这里插入图片描述

过程如下
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

记录拿不拿此商品的决策过程

选择了商品i,即价值为p[i-1,c-vi]+pi,则Rec[i,c]=1

若没有选择商品i,则价值为p[i-1,c],则Rec[i,c]=0
在这里插入图片描述

伪代码
在这里插入图片描述
在这里插入图片描述

从最后一个格子开始倒序判断是否选择商品
在这里插入图片描述

在这里插入图片描述

动态规划解题步骤
在这里插入图片描述

代码为:

//一共有5个商品,购物车体积为13,求能选择的最大价值
public class BackPack {
	public static void main(String[] args) {
		int[] v = {10,3,4,5,4};	//商品的体积
		int[] pic = {24,2,9,10,9};	//商品的价值
		int[][] P = new int[6][14];	//用于记录递推过程(第1个坐标值的(1-5)代表5个商品,第2个坐标值的(1-13)代表购物车的体积)
		int[][] rec = new int[6][14];	//记录决策过程
		//初始化时设置当商品为0时或当购物车体积为0时P[][]都为0,因为后面递推时需要用到这些数据
		for (int i = 0; i < P.length; i++) {
			P[i][0] = 0;
		}
		for (int j = 0; j < P[0].length; j++) {
			P[0][j] = 0;
		}
		
		for (int i = 1; i < 6; i++) {	//商品编号1-5
			for (int j = 1; j < 14; j++) {	//购物车体积1-13
				if(v[i-1]<=j&&P[i-1][j-v[i-1]]+pic[i-1]>P[i-1][j]){	//v[i-1]<=j:背包可以装下商品i
				//P[i-1][j-v[i-1]]+pic[i-1]:装下商品i时的价值,P[i-1][j]:没装商品i时的价值
					P[i][j] = P[i-1][j-v[i-1]]+pic[i-1];	//装下时价值大于没装时,则P[i][j]放装下时的价值
					rec[i][j] = 1;	//选择了商品,则置此时标志为1
				}else{
					P[i][j] = P[i-1][j];	//装下时价值小于没装时,则P[i][j]放没装下时的价值
					rec[i][j] = 0;	//没选择商品,则置此时标志为0
				}
			}
		}
		System.out.println("备忘录为:");
		for (int i = 0; i < 6; i++) {
			for (int j = 0; j < 14; j++) {
				System.out.print(P[i][j]+"\t");
			}
			System.out.println();
		}
		//备忘录的最后一个元素即为结果
		System.out.println("最大价值为:"+P[5][13]);
		
		System.out.println("决策过程为:");
		for (int i = 0; i < 6; i++) {
			for (int j = 0; j < 14; j++) {
				System.out.print(rec[i][j]+"\t");
			}
			System.out.println();
		}
		
		System.out.println("选择的商品编号为:");
		int volume = 13;
		for (int i = 5; i >0 ; i--) {
			if(volume-v[i-1]>=0&&rec[i][volume]==1){
				volume = volume-v[i-1];
				System.out.print(i+"\t");
			}
		}			
	}
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值