秒懂背包问题之完全背包

01背包

https://www.nowcoder.com/practice/2820ea076d144b30806e72de5e5d4bbf

题目:已知一个背包最多能容纳物体的体积为V,现有n个物品第i个物品的体积为wi, 第i个物品的重量为ci。且每种物品可以有无限个(0-1背包,一种物品只有一个)。求当前背包最多能装多大重量的物品。

我们根据0-1背包问题进行改造,因为0-1背包每次只考虑拿一次的最大值,而这里我们可以取 [当前背包重量/当前选中的物品体积] 次。然后求最大值。伪代码如下:

图片说明

 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--){
           for(int j =0;j<=V/vm[i-1][0];j--){
                dp[j] = Math.max(dp[j],dp[j-k*vw[i-1][0]]+k*vw[i-1][1]);
            }
        }
    }
    return dp[V];
}

以上是我们根据0-1背包进行改造而成的。下面我们再进行详细比较进行优化。手写dp如下图:

图片说明

0-1背包问题和完全背包问题的递推关系式区别:
0-1背包的状态由上一条得来,用的是旧数据,所以需要逆向递推;
完全背包的状态由本条前面的数据得来,用的是新数据,所以顺向推即可。(因为我们需要得到前面放了当前物品几次的价值即可,如上图背包容量为5,则当前最大价值为 [当背包容量减去我放当前这个体积]的价值+当前物品体积的价值,即dp[2][5-3]+3, 然后与前一项比较去最大值;再比如容量为6,取dp[2][6-3]+3)。

我们即可以得到递推关系式:
dp[j] = Math.max(dp[j],dp[j-vw[i-1][0]]+vw[i-1][1]),我们发现和0-1背包是一致的。
代码如下:

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--){
           for(int j =0;j<=V/vm[i-1][0];j--){
                dp[j] = Math.max(dp[j],dp[j-vw[i-1][0]]+vw[i-1][1]);
            }
        }
    }
    return dp[V];
}
全部评论

相关推荐

点赞 评论 收藏
分享
尊嘟假嘟点击就送:加v细说,问题很大
点赞 评论 收藏
分享
评论
4
2
分享
牛客网
牛客企业服务