OI中坑点总结(持续更新)
Posted ivanovcraft
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OI中坑点总结(持续更新)相关的知识,希望对你有一定的参考价值。
以下是我个人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,转移非法
以上是关于OI中坑点总结(持续更新)的主要内容,如果未能解决你的问题,请参考以下文章