多重揹包的二進位制拆分法

2022-04-28 20:15:11 字數 1339 閱讀 6755

在多重揹包的直接拆分法中,個數為$c[i]$的物體被拆成$c[i]$種不同的物體

這樣就使得物體的種類增加了很多,使得演算法效率很低。

上述方法把$c[i]$拆成$c[i]$個1,於是任意選擇可以表示出$1$到$c[i]$之間的所有數,從而達到多重揹包的目的

想到,從$2^0,2^1,2^2,...,2^k$任意選擇可以表示出$1$到$2^-1$之間的所有數

於是就有了二進位制拆分法

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

令$t=\sum_^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 #include2 #include3 #include4

#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--)

9using

namespace

std;

10const

int n=101,m=100001;11

intn,m,t,p,ans,a[n],c[n];

12bool

f[m];

13 il void calc(int

x)14

17 t=x-t/3;p--;18}

19int

main()

2036 yes(k,m,t)f[k]|=f[k-t];37}

38 go(i,1,m)if(f[i])ans++;

39 printf("

%d\n

",ans);40}

41return0;

42 }

view code

多重揹包(二進位制拆分優化)

多重揹包基本模型如下 給定n種物品,其中第i種物品的體積為vi,價值為wi,並且有ci個。有一容積為m的揹包,要求選擇若干個物品放入揹包,使得物品總體積不超過m的前提下,物品價值總和最大。輸入格式 第一行兩個整數,n,m,用空格隔開,分別表示物品種數和揹包容積。接下來有 n 行,每行三個整數 vi,...

POJ1014 多重揹包(二進位制拆分)

題目鏈結 題目大意 給出6個數,分別代表價值為1 6的6種物品的數量,求能否在價值相同的情況下平分這些物品。思路 多重揹包。一開始拆成01揹包來做,寫了三層迴圈,很顯然結果tle了。後來上網看了一下題解,大致意思是把每一種物品的數量拆成1,2,4,8,這樣的2的n次方數,比如將12拆成1,2,4,5...

東東與 ATM 多重揹包 二進位制拆分

題意 一家銀行計畫安裝一台用於提取現金的機器。機器能夠按要求的現金量傳送適當的賬單。機器使用正好n種不同的面額鈔票,例如d k,k 1,2,n,並且對於每種面額d k,機器都有n k張鈔票。例如,n 3,n 1 10,d 1 100,n 2 4,d 2 50,n 3 5,d 3 10 表示機器有10...