01背包 动态规划(三)

01背包问题详解,暴力递归改动态规划

测试数据:

		int n=5;//物品个数
		int m=20;//背包容量
		int[] weight=new int[]{0,2,3,4,5,9};//物品重量
		int[] value=new int[]{0,3,4,5,8,10};//物品价值

1.递归版本:

private static int knapsack(int n,int m,int[] w,int[] v) {
		if(n==0||m==0){
			return 0;
		}else if((m>w[n])&&((knapsack(n-1, m-w[n], w, v)+v[n])>knapsack(n-1, m, w, v))){
			return knapsack(n-1, m-w[n], w, v)+v[n];
		}else{
			return knapsack(n-1, m, w, v);
		}
	}

2.分析可变参数,哪几个可变参数的值能代表返回状态,几个可变参数,就构造几维表。

    本题中,背包所装得物品的最大价值只与背包容量和物品个数有关,所以dp表为二维:


3.根据base case填表:

if(n==0||m==0){
			return 0;
		}

n\m 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0                                        
2 0                                        
3 0                                        
4 0                                        
5 0                                        
4.分析一个普遍位置的规律:
if((m>w[n])&&((knapsack(n-1, m-w[n], w, v)+v[n])>knapsack(n-1, m, w, v))){
			return knapsack(n-1, m-w[n], w, v)+v[n];
		}else{
			return knapsack(n-1, m, w, v);
		}

如果一个位置的列(即背包容量)>它的w[n](即物品质量),要知道这个位置的值,就得知道它(上一行,本列+w[n])+v[n] 元素的值和(上一行,本列) 元素的值,取其二者中最大值;

如果一个位置的列(即背包容量)<= 它的w[n](即物品质量),要知道这个位置的值,就得知道它(上一行,本列)元素的值。


补全dp表(略,见下图):

n\m 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0
1 0                                        
2 0                                        
3 0                                        
4 0                                        
5 0                                        

动态规划的代码为:

// dp
	private static int dpknapsack(int n, int m, int[] w, int[] v) {
		int[][] dp = new int[n + 1][m + 1];
		// for (int i = 0; i < n + 1; i++) {
		// dp[i][0] = 0;
		// }
		// for (int j = 0; j < m + 1; j++) {
		// dp[0][j] = 0;
		// }
		for (int i = 1; i < n + 1; i++) {
			for (int j = 1; j < m + 1; j++) {
				if (j > w[i]) {
					int value1 = dp[i - 1][j - w[i]] + v[i];
					int value2 = dp[i - 1][j];
					dp[i][j] = value1 > value2 ? value1 : value2;
				} else {
					dp[i][j] = dp[i - 1][j];
				}
			}
		}

		for (int x = 0; x < n + 1; x++) {
			for (int y = 0; y < m + 1; y++) {
				System.out.print(dp[x][y] + "\t");
			}
			System.out.println("");
		}
		return dp[n][m];
	}



全部评论

相关推荐

11-01 08:48
门头沟学院 C++
伤心的候选人在吵架:佬你不要的,能不能拿户口本证明过户给我。。球球了
点赞 评论 收藏
分享
10-25 02:13
门头沟学院 C++
牛客7351937293号:8.27笔试10.22评估
投递小米集团等公司10个岗位
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务