0
点赞
收藏
分享

微信扫一扫

动态规划——背包问题

敬亭阁主 2022-03-26 阅读 53

动态规划——背包问题(运输货物问题)

先学习 01背包问题
背包问题可大致分为【完全背包问题】和【多重背包问题】
在这里插入图片描述

分析问题:
原问题:在满足重量约束的条件下,将这 m 件物品选择性的放入容量位W的背包中所能获得的最大利润
子问题:在满足重量约束的条件下,将 前 i(i<=m)件物品选择性的放入容量为 j(j<=W)的背包中所能获得的最大利润
定义状态: f(i,j)为前 i 件物品选择性放入 容量为 j (j<= W)中获得最大利润。那么 f(m,W)就是我们的原问题。
存在两个参数,所以创建一个二维DP数组。

vi表示第 i 件物品的价值,wi 表示第 i 件物品的重量

寻找状态转移方程
边界条件(初始条件)

构建方程:

  • 当 i > 1 和 j > 1 的情况: 考虑以下:由一个容量大小为j的背包,已经规划好了 前面 i-1 件物品的装载方案,现在你只需要考虑装不装第 i 件物品。

所以接下来,考虑两种情况:

转移方程:
在这里插入图片描述

代码实现:

	public static void valueMax(int[] weight, int[] value, int capacity) {
		//这里 weight和value是一样从的。   表示 物品的个数
		int num = value.length;
		int[][] dp = new int[weight.length+1][capacity+1];
		//记录放入商品的情况
		int[][] path = new int[weight.length+1][capacity+1];
				
		// 第一行  将可以放下的 第一物品 放入
		for (int j = 0; j < dp.length; j++) {
			dp[j][0] = 0;
		}
		// 第一列   背包容量为1的 ,可以装下哪些物品
		for (int i = 0; i < dp[0].length; i++) {
			dp[0][i] = 0;
		}

		// 然后从 第 一行和第一列 开始 
		for (int i = 1; i < dp.length; i++) {
			for (int j = 1; j < dp[0].length; j++) {
				if (j >= weight[i-1]) {	//这里因为是从第一行开始 使用对应的第一个是  weight[i-1]
					// 还是 应为 我们 下标是从 1开始的,所以对应的公式需改动  即 物品的重量和价格需 下标要减1
					//dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
					
				//	dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i-1]] + value[i-1]);	
					
					// 为了 存储 选择 放入背包的是哪些物品 所以使用 选择来实现
					if(dp[i-1][j] < dp[i-1][j-weight[i-1]]+value[i-1]) {
						dp[i][j] = dp[i-1][j-weight[i-1]]+value[i-1];
						path[i][j] = 1;
					}else {
						dp[i][j] = dp[i-1][j];
					}
					
				} else {
					dp[i][j] = dp[i - 1][j];
				}
				
			}
		}

		System.out.println("动态规划表如下:");
		for (int i = 0; i < dp.length; i++) {
			for (int j = 0; j < dp[i].length; j++) {
				System.out.print(dp[i][j] + "\t");
			}
			System.out.println();
		}	
		int i=path.length-1;
		int j=path[0].length-1;
		while(i>0 && j>0) {
			if(path[i][j] == 1) {
				System.out.printf("第%d个商品放入背包\n",i);
				j-=weight[i-1];
			}
			i--;
		}
	}
举报

相关推荐

0 条评论