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