秒懂背包问题之0-1背包

01背包

http://www.nowcoder.com/questionTerminal/2820ea076d144b30806e72de5e5d4bbf

1.分析:

dp[i][j]表示:对于前i个物品,当前背包的容量为j时,这种情况下可以装下的最大价值是dp[i][j]。
如果你没有把这第i个物品装入背包,那么很显然,最大价值dp[i][j]应该等于dp[i-1][j]。你不装嘛,那就继承之前的结果。
如果你把这第i个物品装入了背包,那么dp[i][j]应该等于dp[i-1] [ j-vm[j-vm[i-1][0] ] + vm[i-1][1]。但还是需要和不装入进行大小比较,取价值最大的。

关键代码如下:

 public int knapsack (int V, int n, int[][] vw) {
        // write code here
        int[][] dp = new int[n+1][V+1];
        for(int i = 1; i<=n;i++){
            for(int j = 1;j<=V;j++){
                if(j<vw[i-1][0]){
                    dp[i][j] = dp[i-1][j];
                }else{
                    dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-vw[i-1][0]]+vw[i-1][1]);
                }
            }
        }
        return dp[n][V];
    }

2.手写dp表

图片说明

3.考虑空间的优化

如上面分析所示,我们每次更新第 i 行的数据时,只与 i-1 行有关系,所以我们完全可以使用一维数组来存储dp状态。但我们需要倒着进行更新(因为我们需要用到下标较小的状态)。

核心循环代码如下:

    public int knapsack (int V, int n, int[][] vw) {
        // write code here
        int[] dp = new int[V+1];
        for(int i = 1; i<=n;i++){
            for(int j = V;j>=1;j--){
                if(j>vw[i-1][0]){
                    dp[j] = Math.max(dp[j],dp[j-vw[i-1][0]]+vw[i-1][1]);
                }
            }
        }
        return dp[V];
    }
全部评论
空间优化时,if(j>vw[i-1][0])应该改为if(j>=vw[i-1][0])
3 回复 分享
发布于 2021-06-08 15:40
dp[2][10]=Math.max(dp[1][10], dp[1][10-vw[1][0])+vw[1][1]) =Math.max(dp[1][10], dp[1][10-10]+vw[1][1]) = Math.max(3,4)=4
点赞 回复 分享
发布于 2021-11-04 12:13

相关推荐

10-25 00:32
香梨想要offer:感觉考研以后好好学 后面能乱杀,目前这简历有点难
点赞 评论 收藏
分享
评论
13
2
分享
牛客网
牛客企业服务