动态规划之五种背包问题

目录

一、背包内物品的总重量最大

     1.1 0-1背包问题(二维数组求解)

     1.2 0-1背包问题(一维数组求解)

     1.3 完全背包问题(一维数组求解)

二、背包内物品的总价值最大

     2.1 0-1 背包问题(一维数组求解)

     2.2 完全背包问题(一维数组求解)


一、背包内物品的总重量最大

题目:有n件物品,每件物品的重量为 weight = {2, 2, 4, 6, 3} 。现有一个容量为 w = 9 的背包,问背包内物品的总重量最大是多少。

     1.1 0-1背包问题(二维数组求解)

 0123456789
01010000000
11010100000
21010101010
31010101000
41010101011
	public static int knapsack(int[] weight, int n, int w) {
	  boolean[][] dp = new boolean[n][w+1]; // 默认值false
	  dp[0][0] = true;  // 第一行的数据要特殊处理,可以利用哨兵优化
	  
	  if (weight[0] <= w) 
	    dp[0][weight[0]] = true;
	  
	  for (int i = 1; i < n; ++i) { // 动态规划状态转移
	    for (int j = 0; j <= w; ++j) {

	      if (dp[i-1][j]==true) {
	    	  dp[i][j] = dp[i-1][j];
	    	  
	    	  if(j <= w - weight[i])
	    		  dp[i][j + weight[i]] = true;
	      }	    	  
	    }
	  }
	  for (int i = w; i >= 0; --i) { // 输出结果
	    if (dp[n-1][i] == true) return i;
	  }
	  return 0;
	}

     1.2 0-1背包问题(一维数组求解)

       和二维数组原理类似,只是每次会更新一维数组;

	public static int knapsack2(int[] items, int n, int w) {
	  boolean[] dp = new boolean[w+1]; // 默认值false
	  dp[0] = true;  // 第一行的数据要特殊处理,可以利用哨兵优化
	  if (items[0] <= w) 
	    dp[items[0]] = true;

	  for (int i = 1; i < n; ++i) { // 动态规划
		  
	    for (int j = w-items[i]; j >= 0; --j) //把第i个物品放入背包
	      if (dp[j]==true) dp[j+items[i]] = true;
	  }
	  for (int i = w; i >= 0; --i)          // 输出结果
	    if (dp[i] == true) return i;
	  
	  return 0;
	}

     1.3 完全背包问题(一维数组求解)

完全背包问题解题思路,每件物品可重复选择,weight = {2, 2, 4, 6, 3},w=9,dp[0 - w] 数组记录重量为 i 的最小次数。

状态变化如下:

 0123456789
00010203040
10010203040
20010102020
30010101020
40011121222
	public static int knapsack3(int[] weight, int n, int w) {
		int[] dp = new int[w+1];
		int min = Integer.MAX_VALUE;
		if (weight[0] <= w) 
			dp[weight[0]] = 1;

		for (int i = 0; i < n; ++i) {
			for (int j = 0; j <= w; ++j) {
				if (j == 0 || dp[j] != 0 && j <= w - weight[i]) {
					if(dp[j+weight[i]] != 0)
						dp[j+weight[i]] = Math.min(dp[j+weight[i]], dp[j] + 1);
					else
						dp[j+weight[i]] = dp[j] + 1;
				}
				if(j == w && dp[w] != 0)
					min = Math.min(min, dp[w]);
			}
		}
		return min;
	}

二、背包内物品的总价值最大

题目:有n件物品,每件物品的重量为 weight ={2, 2, 4, 6, 3}, value = {3, 4, 8, 9, 6}。现有一个容量为 w = 10 的背包,问如何选取物品放入背包,使得背包内物品的总重量最大。

     2.1 0-1 背包问题(一维数组求解)

wn            
105            
weightvalue 012345678910
23000333333333
24100447777777
4820044881212151515
6930044881212151517
36400448101214151818
	public static int backpack(int[] weight, int[] value, int n, int w) {
		
		int[] dp = new int[w+1];
		
		for(int i=0; i<n; i++) {
			for(int j=w; j>=0; j--) {
				if(j >= weight[i])
					dp[j] = Math.max(dp[j], dp[j-weight[i]] + value[i]);
			}
		}
		return dp[w];
	}

     2.2 完全背包问题(一维数组求解)

wn            
105            
weightvalue 012345678910
23000336699121215
2410044881212161620
4820044881212161620
6930044881212161620
36400448101214161820
	public static int backpack(int[] weight, int[] value, int n, int w) {
		
		int[] dp = new int[w+1];
		
		for(int i=0; i<n; i++) {
			System.out.println(i + ":");
			for(int j=0; j<=w; j++) {
				if(j >= weight[i])
					dp[j] = Math.max(dp[j], dp[j-weight[i]] + value[i]);
				System.out.print(dp[j] + ", ");
			}
			System.out.println();
		}
		return dp[w];
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值