以下是我个人OI生涯中遇到的坑点的一个小总结,可能是我太菜了,总是掉坑里,请大佬勿喷
1,多重背包的转移顺序
//默认每个物品体积为一(不想打码……) //dp[i]表示占用背包容量i所能获得的最大价值 for(int i=1;i<=n;i++) for(int j=sum;j>0;j--) //sum表示背包最大容量 for(int k=0;k<=num;k++) //num表示这个物品的数量,k表示选取当前物品k件 if(j>=k) dp[j]=min(dp[j],dp[j-k]+value);
简单的多重背包模板,对于学过的人,大概清晰易懂吧
//dp[i]表示占用背包容量i所能获得的最大价值 for(int i=1;i<=n;i++) for(int k=0;k<=num;k++) //num表示这个物品的数量,k表示选取当前物品k件 for(int j=sum;j>k;j--) //sum表示背包最大容量 dp[j]=min(dp[j],dp[j-k]+value);
很相似的代码,只是改了转移顺序,但是为什么会错呢?
类比01背包的倒序转移,
考虑对于某种物品,标程中先枚举 j ,再枚举 k ,这样对于每个位置 j ,只能先于位置 j - i ,由 j - i ( i ∈ [ 0 , k ] )转移一次
而错误写法中,对于位置 j ,可以由转移过的位置 j - i 转移而来
这为什么会导致错误呢?考虑在 j 之前, j - i 已经由 j - i1 - i2 转移而来,多重背包的物品是可以组合的,所以以上的转移等价于 dp[ j - i1 - i2 ] 直接转移到 dp[ i ] ,而我们不能保证 i1 + i2 <= num ,即可能会取多于物品总数的物品
举个例子:
物品数量为7,我们枚举位置13,由8转移而来,而在此之前,位置8由4转移而来,等价于位置13由位置4转移而来,13-4=9>7,转移非法
原文地址:https://www.cnblogs.com/ivanovcraft/p/9496574.html
时间: 2024-10-21 10:43:59