多重背包(二进制拆分法)

众所周知,从2,21,...,2k-1这k个2的整数次幂中选出若干相加,可以表示出0~2k-1之前的任意整数

所以我可以把Ci个物品分解成p+2个

即若干个2的幂次方为系数的体积(对下面的这些体积进行0/1背包)

20*Vi+...+2p*Vi+Ri*Vi  

for(int i=1;i<=n;i++){//种类数
            int temp=c[i]; int now=1;
            while(1){    //把c[i]拆解成若干个2的幂次方 
                if(temp>now){
                    temp-=now;
                    for(int j=m;j>=now*a[i];j--)
                        if(dp[j-now*a[i]])
                        dp[j]=1;
                        now*=2;
                }else{
                    for(int j=m;j>=temp*a[i];j--)
                    if(dp[j-temp*a[i]])
                        dp[j]=1;
                    break;
                }
            }
        }

猜你喜欢

转载自www.cnblogs.com/wmj6/p/10389796.html