码迷,mamicode.com
首页 > 其他好文 > 详细

OI中坑点总结(持续更新)

时间:2018-08-18 13:17:28      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:表示   多重背包   min   code   sans   strong   枚举   个人   组合   

以下是我个人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中坑点总结(持续更新)

标签:表示   多重背包   min   code   sans   strong   枚举   个人   组合   

原文地址:https://www.cnblogs.com/ivanovcraft/p/9496574.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!