【*对二进制优化的一些理解*】(后续完善……)

主要总结下快速幂的二进制思想与DP中多重背包的二进制优化:
*1*.快速幂:
看下模板:
   
   
long long pow2( int a, int b )//求a的b次幂
{
     long long r = 1, base = a;
     while ( b != 0 )
     {
         if ( b%2==1 )
             r *= base;
         base *= base;
         b /= 2;
     }
     return r;
}
原理:将计算a的b次幂时普通的 b次 循环,改为了按照b对应的二进制数每一位的权值及该位上是0或1,从而判断是否需要乘上该位时二进制对应的权值次方。
举个例子。对于求a的21次方(不要管为什么是21),10进制的21对应的二进制数为10101,这时候程序会一边计算21所对应的某一位二进制数,如果是1便让结果r乘上当前的二进制位的权值(即乘上a的n次方)然后权值base平方得到二进制下一位的权值。
其实我很佩服我是怎么纠结着写到这里的。。。目前就理解到这里了。

*2*DP多重背包:
同样先放模板:

int DP()
{
for(int i=1;i<=n;i++)
{
if(W[i]*Qo[i]>C)//如果个数乘上单位体积大于背包体积就按完全背包算
{
for(int c=0;c<=C;c++)
if(c>=W[i]) F[c]=max(F[c],F[c-W[i]]+V[i]);
}
else//否则先多重再o1
{
int k=1,amount=Qo[i];
while(k<amount)
{
for(int c=C;c>=k*W[i];c--)//计算加上一个体积为k*W[i]的物品
F[c]=max(F[c],F[c-k*W[i]]+k*V[i]);
amount-=k;
k+=k;//二进制加
}

for(int c=C;c>=amount*W[i];c--)
F[c]=max(F[c],F[c-amount*W[i]]+amount*V[i]);//01背包加上剩下的来算最优值
}
}
return F[C];

}

首先描述下多重背包的写法:
1)对于每一种物件,如果其数量足够多以致于整个背包全放这一种物件都不够,那么对该物件做一遍完全背包即可;
2)而如果当某物件的件数*单件体积小于背包体积的话,那么我们就需要思考,到底放几个该物件才最优?而这也是此时的DP转移思路,即枚举放n个该物件进背包的最优值(n≥1并且n≤该物件的件数),即做n遍01背包。

所以在第二步中就出现可以优化的地方了,既然逐个枚举选物件的个数,那么这就产生了重复枚举的弊端。这很显然,比如选择4件该物件的最优值就已经被选1件和选3件时的方案找到过了。
因此在这里根据二进制的特点我们只需要做 小于该物件总件数的2的次幂 ,并且最后再把余下的物件个数当做剩下的一个做一遍01背包即可。这里将本来的O(件数*背包体积)减小到(log2件数*背包体积)。















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值