【动态规划之背包问题】——0-1背包问题

0 - 1 背包问题

给你一个可装载重量为 W 的背包和 N 个物品, 每个物品有重量和价值两
个属性。 其中第 i 个物品的重量为 wt[i] , 价值为 val[i] , 现在让你用
这个背包装物品, 最多能装的价值是多少?

例如:

N = 3, W = 4
wt = [2, 1, 3]
val = [4, 2, 3]

返回: 6

动态规划的套路:

  1. 要明确两点, 「状态」 和「选择」 。
    状态有两个, 就是「背包的容量」 和「可选择的物品」 。
    选择就是「装进背包」 或者「不装进背包」 。

框架:

for 状态1 in 状态1的所有取值:
	for 状态2 in 状态2的所有取值:
		for ...
			dp[状态1][状态2][...] = 择优(选择1, 选择2...)
  1. 要明确 dp 数组的定义
    • dp[i][w] 的定义如下: 对于前 i 个物品, 当前背包的容量为 w , 这种
      情况下可以装的最大价值是 dp[i][w]
    • dp[3][5] = 6 , 其含义为: 对于给定的一系列物品中, 若只对前 3 个物品进行选择, 当背包容量为 5 时, 最多可以装下的价值为 6
    • 答案就是 dp[N][W]
    • base case 就是 dp[0][..] = dp[..][0] = 0 , 因为没有物品或者背包没有空间的时候, 能装的最大价值就是 0。

细化后的框架:

int dp[N+1][W+1]
dp[0][..] = 0
dp[..][0] = 0

for i in [1..N]:
	for w in [1..W]:
		dp[i][w] = max(
			把物品 i 装进背包,
			不把物品 i 装进背包
		)
return dp[N][W]
  1. 根据「选择」 , 思考状态转移的逻辑
    dp[i][w] 表示: 对于前 i 个物品, 当前背包的容量为 w 时, 这种情况
    下可以装下的最大价值是 dp[i][w]
    • 如果你没有把这第 i 个物品装⼊背包, 那么很显然, 最大价值 dp[i][w]应该等于 dp[i-1][w] , 继承之前的结果。
    • 如果你把这第 i 个物品装进了背包, 那么 dp[i][w] 应该等于 dp[i-1][w- wt[i-1]] + val[i-1] 。 其中:dp[i-1][w - wt[i-1]] 也很好理解: 你如果装了第 i 个物品, 就要寻求剩余重量 w - wt[i-1] 限制下的最大价值, 加上第 i 个物品的价值val[i-1]
for i in [1..N]:
	for w in [1..W]:
		dp[i][w] = max(
			dp[i-1][w],
			dp[i-1][w - wt[i-1]] + val[i-1]
)
return dp[N][W]

完整代码求解为

public class bag_2_15 {
    public static int knapsack(int W,int N,int[] wt,int[] val){
        int[][] dp = new int[N + 1][W + 1];
        for (int i = 1; i <= N; i++) {
            for (int w = 0; w <= W; w++) {
                if (w - wt[i - 1] < 0){
                    //背包容量不够,则不能装入背包
                    dp[i][w] = dp[i - 1][w];
                }else {
                    //装入或者不装入背包,择优
                    dp[i][w] = Math.max(dp[i - 1][w - wt[i - 1]] + val[i - 1],dp[i - 1][w]);
                }
            }
        }
        return dp[N][W];
    }

    public static void main(String[] args) {
        System.out.println(knapsack(4,3,new int[]{2,1,3},new int[]{4,2,3}));
    }
}

参考:labuladong

posted @ 2021-03-28 21:14  your_棒棒糖  阅读(43)  评论(0编辑  收藏  举报