部分揹包 poj1014 Dividing

2021-07-04 04:16:54 字數 1240 閱讀 4820

一種物品,限制了數量,那就不能按照完全揹包的寫法去寫了

如果按照01揹包的方法去寫,如果數量很大,那麼必然會超時,那有沒有什麼好辦法呢?

我們先講神奇的二進位制思想

我們都知道,任何乙個十進位制都能轉換成二進位制(廢話)

那麼二進位制就會對應著許多二進位(還是廢話)

每個二進位都是2的倍數(肯定啊)

所以反過來講,任何乙個數字,都能由2的倍數相加組成(........)

再來看乙個二進位111111(2),一共有6個二進位,對應的數字分別是32,16,8,4,2,1

那麼,我只用這6個數字,我就能描述出1~63中所有的情況了..

其實道理很明白哇,64的二進位制是1000000(2),63的二進位制是111111(2)

所以只要小於63的,都能通過那些二進位重新組成這個數字

說二進位制思想有什麼用呢?假如我們的n等於63,本來如果我用01揹包,我需要做63次

如果我用二進位制思想去分解n,可以得到32,16,8,4,2,1,那麼我只需要拿這6個去做01揹包,就能表示出所有的情況了

換句話說,在列舉這裡的複雜度,從o(n)降到了o(logn),優化非常明顯!

#include#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

typedef pairpii;

const int mx = 5e5 + 5;

const int inf = 0x3f3f3f3f;

int a[10];

bool dp[mx];

void solve(int t, int v)

}int main()

if(!v) break;

printf("collection #%d:\n", ++ansk);

if(v % 2 != 0)

v /= 2;

dp[0] = true;

for(int i = 1; i <= 6; i++)

solve(a[i] * i, v);//肯定有時候不能完全分解,還會剩下一點點,單獨做一次01揹包

}if(dp[v]) printf("can be divided.\n\n");

else printf("can't be divided.\n\n");

}return 0;

}

POJ1014 多重揹包

今天開始dp了,第一道多重揹包,模板題,還是想了很久,太弱了 題意 一行給出6個數,表示從1到6,6個不同權值的個數.求能否將所有權值不分割的分成權值相等的兩份.首先總權值為奇數的肯定不符合要求,接下來就是乙個多重揹包了.多重揹包的二進位制拆分我的理解大概是 首先將乙個數按二進位制拆分之後可以用拆分...

poj1014多重揹包

做這個題目的時候受到dp時取min還是max的影響,不知道最後該怎麼做,看了大神的blog有了思路,直接貼上 了。出處 優you的部落格 memory time 656k 16ms 多重揹包 二進位制優化 include includeusing namespace std int n 7 價值為i...

poj 1014多重揹包

題意 給出價值為1,2,3,4,5,6的6種物品數量,問是否能將物品分成兩份,使兩份的總價值相等。思路 求出總價值除二,做多重揹包,需要二進位制優化。include include includeusing namespace std int n 7 int v,sum bool flag int ...