zoukankan      html  css  js  c++  java
  • 多重背包的二进制拆分法

    在多重背包的直接拆分法中,个数为$c[i]$的物体被拆成$c[i]$种不同的物体

    这样就使得物体的种类增加了很多,使得算法效率很低。

    上述方法把$c[i]$拆成$c[i]$个1,于是任意选择可以表示出$1$到$c[i]$之间的所有数,从而达到多重背包的目的

    想到,从$2^0,2^1,2^2,...,2^k$任意选择可以表示出$1$到$2^{k+1}-1$之间的所有数

    于是就有了二进制拆分法

    首先找到最大的$k$,使得$sum_{i=0}^{k}2^i<=c[i]$

    令$t=sum_{i=0}^{k}2^i$,易知,上面$k+1$个数可以组成$1$到$t$之间的任何数

    那$t+1$到$c[i]$之间的数怎么表示呢?

    令$p=c[i]-t$,再拆出一个p,就可以了,理由如下:

    $c[i]=p+t,c[i]-1=p+t-1...$依次类推

    由于$1$到$t$已经被表示,所以这样一来$1$到$c[i]$之间的每个整数都可以被表示

    具体来说,就是把数量为$c[i]$的物体分为$k+2$个,它们的体积分别为$2^0*v[i],2^1*v[i],...,2^k*v[i],p$

    Code:

    是$POJ1742Coins$的代码,虽然会TLE,就当打了个二进制拆分法的板子叭

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define Ri register int
     5 #define il inline
     6 #define mem(a,b) memset(a,b,sizeof(a))
     7 #define go(i,a,b) for(Ri i=a;i<=b;i++)
     8 #define yes(i,a,b) for(Ri i=a;i>=b;i--)
     9 using namespace std;
    10 const int N=101,M=100001;
    11 int n,m,t,p,ans,a[N],c[N];
    12 bool f[M];
    13 il void calc(int x)
    14 {
    15     t=1,p=0;
    16     while(t<=x){t+=(t<<1);p++;}
    17     t=x-t/3;p--;
    18 }
    19 int main()
    20 {
    21     while(scanf("%d%d",&n,&m)&&n)
    22     {
    23         mem(f,0);ans=0;
    24         go(i,1,n)scanf("%d",&a[i]);
    25         go(i,1,n)scanf("%d",&c[i]);
    26         f[0]=1;
    27         go(i,1,n)
    28         {
    29             calc(c[i]);
    30             go(j,0,p)
    31             {
    32                 int q=1;if(j)q*=2;
    33                 yes(k,m,a[i]*q)
    34                 f[k]|=f[k-a[i]*q];
    35             }
    36             yes(k,m,t)f[k]|=f[k-t];
    37         }
    38         go(i,1,m)if(f[i])ans++;
    39         printf("%d
    ",ans);
    40     }
    41     return 0;
    42 }
    View Code
    光伴随的阴影
  • 相关阅读:
    linux使用命令记录
    (转)如何连接远程桌面
    PLSQL将查询结果复制为insert语句
    用foxPro打开dbf文件
    (转)PLSQL新手使用教程
    CPN TOOL使用
    运行mongoDB
    PLSQL连接数据库
    剑指 Offer 10- II. 青蛙跳台阶问题(简单)
    剑指 Offer 10- I. 斐波那契数列(简单)
  • 原文地址:https://www.cnblogs.com/forward777/p/10993426.html
Copyright © 2011-2022 走看看