动态规划--背包问题

背包问题

一个旅行者随身携带一个背包。可以放入背包的物品有n种,每种物品的重量和价值分别为wi, vi如果背包的最大重量限制是b,每种物品可以放多个.怎样选择放入背包的物品以使得背包的价值最大?不妨设上述wi,vi, b都是正整数.
在这里插入图片描述
1、问题建模
目标函数 {v1x1 + v2x2 + …+ vnxn}max
约束条件 wixi <= b
在这里插入图片描述

2、子问题界定
在这里插入图片描述
3、优化函数的递推方程
老师这里的第一个递推方程应该不对,题目是每个物品可以装n种,而不是一种;

所以Fk(y) = max{ Fk-1(y),Fk(y-nwk) + nvk } n是装入第k个物品的数量

当y-nwk<0时,Fk(y-nwk)取负无穷大;
在这里插入图片描述
4、界定最小子问题

当k=0是,所有的F0(y)都等于0;

当k=1时,问题最小,此时F1(y) = y/w1向下取整 * v1;

5、明确计算顺序

k=1, y= 1 2 3 … y

k=2, y= 1 2 3 … y

.

.

.

k=k,y= 1 2 3 … y

6、保存问题结果

m[k] [y] = 装入前k个物品最大限重y时,最大价值

7、标记函数

s[k] [y] = 装入前k个物品最大限重y时,最大价值时,装入的第k个物品的数量

标记函数的取值与老师不一样
老师标记的是最大标号
在这里插入图片描述
一个问题实例的解过程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
0-1背包问题用这节课老师讲的递推方程很好解,复杂度很低,老师这节课讲的问题更像一个0-1背包问题

F(k,y) = max{F(k-1,y),F(k,y-wk)+vk};

多背包问题如果没有物品的限制,更像是可以一个个背包问题求解取得最大值再合并

二位背包限制条件增加一种,可能需要多增加一层遍历

子问题F(k,b,v) 也就是装入前k种物品,重量不超过b,体积不超过v;

递推方程F(k,b,v) = F(k-1,b-nbk,v-nvk) + nVk(值n倍的第k个物品的价值)
java代码实现

//背包问题
	//问题描述:一个背包,可以放入背包的物品有n种,每种物品的重量和价值分别为wi,vi,如果背包的最大重量限制是b,每种物品可以放多个,
	//怎样选择放入背包的物品使得背包的价值最大
	public void knapsackProblem(int n, int b, int[] w, int[] v) {
		int[][] m = new int[n+1][b+1];
		int[][] s = new int[n+1][b+1];
		
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= b; j++) {
				for (int k = 0; k <= j/w[i-1]; k++) {
					int temp = m[i-1][j-k*w[i-1]] + k*v[i-1];
					if(temp > m[i][j]) {
						m[i][j] = temp;
						s[i][j] = k;
					}
				}
			}
		}
		getKnapsackProblem(n, b, m, s, w, v);
		
	}

	private void getKnapsackProblem(int n, int b, int[][] m, int[][] s, int[] w, int[] v) {
		System.out.println("当背包只装入前" + n + "个物品,装入最大重量为" + b + "时,能装入的最大价值是" + m[n][b] + ", 装入第" + n + "个物品的数量是" + s[n][b]);
		if(n == 0 || b == 0) {
			return;
		}
		getKnapsackProblem(n-1, b-s[n][b]*w[n-1], m, s, w, v);
	}

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值