题解 | #01背包#

01背包

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

2022.0906算法第55题01背包
这道题也不容易想,但是竟然归为简单题,
我当时没想到需要和dp[i-1][j-vw[i-1][0]]离的那么远的值发生关系
1、状态矩阵建立了
2、初始值没弄ing错
3、状态转移方程没搞明白,已经把一个例子的状态矩阵写出来了
        但是没想明白dp[i][j]是怎么得到的,有几个方向过去的
解释:
dp[i][j]可以理解为物品i放置或者不放置,就这两种情况‘
当然这是有前提的,就是当前的物品i有这两种选择
下面就要分情况讨论了:
当物品i的体积大于背包的容量时,那肯定是没办法放的,也就是只能选择i-1个物品的最大值dp[i][j]=dp[i-1][j];
当物品i的体积小于等于背包的容量时,此时可以选择物品i是否放置,此时就有两种情况
1、物品i放置,则要考虑背包取出物品i体积的剩余空间,装入前i-1个物品的最大重量(注意此时物品i已经使用,不能在使用了,所以时i-1)
        ,这是将去除物品i的剩余体积对应的最大重量加上物品i的重量就是此时背包的重量
2、物品i不放置,不放置的结果和上面体积大于背包的容量时一样,都是选择i-1个物品的最大值dp[i][j];
        针对物品i的体积小于等于背包的容量的情况,取1和2的最大值就是物品0-i选取,容量为i的背包,的最大重量。
这次的理解应该算是比较准确的了,
int knapsack(int V, int n, vector<vector<int> >& vw) {
    //状态矩阵,表示从i个物品中选取,背包容量为j时的最大重量
    //明确状态矩阵的含义,下标的含义十分重要。。。
    //这里面就有初始化了。直接将左边界和上边界赋值为0,这就是初始化
    vector<vector<int>> dp(n+1,vector<int>(V+1));
    //循环计算状态矩阵中的每一个值
    for(int i=1;i<=n;i++){
        for(int j=1;j<=V;j++){
            //判断此时是否能选择物品i的条件
            //当背包容量小于等于物品i的体积时,表明此时可以选择物品i,
            //但是这时还是需要考虑是否选择物品i
            //1、物品i不放置,则此时dp[i][j]就等于前i-1个物品装入背包容量为j的最大重量也就是dp[i-1][j]
            //2、物品i放置,则需要考虑背包容量j去除物品i的体积,
            //    剩余的体积装入前i-1个物品的最大重量(注意此时物品i已经选择,只能从前i-1个物品中进行选择。
            //    此时的重量为前i-1个物品装入当前容量j去除物品i的体积剩余体积的最大重量dp[i-1][j-vw[i-1][0]]
            //    在加上物品i的重量
            //将1和2取最大值就是当前物品的最大值。
            if(vw[i-1][0]<=j){
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-vw[i-1][0]]+vw[i-1][1]);
            }
            //当vw[i-1][0]>j时,无法选择物品i,只能选择从前i-1个物品中选取
            //此时dp[i][j]就等于前i-1个物品装入背包容量为j的最大重量也就是dp[i-1][j]
            else{
                dp[i][j]=dp[i-1][j];
            }
        }
    }
    return dp[n][V];    
}


针对01背包,每个物品只能选择一次。
完全背包则有无数个物品,每个物品可以多次选择(这个问题可以尝试,需要对状态转移方程进行修改)
多重背包每个物品的数量各不相同
分组背包按组分开,每组选择一个。。。
#算法题#
全部评论

相关推荐

头像
不愿透露姓名的神秘牛友
04-29 12:10
点赞 评论 收藏
转发
点赞 评论 收藏
转发
2 1 评论
分享
牛客网
牛客企业服务