POJ 1014 Dividing 多重揹包問題

2021-09-06 04:20:34 字數 1454 閱讀 2023

這題做了將近乙個月,斷斷續續的看揹包問題,今天總於一口氣把揹包九講中的前三講看完了。

為什麼這樣正確呢?

證明:(1) 數列1,2,4,…,2^(k-1),n-2^k+1中所有元素的和為n,所以若干元素的和的範圍為:[1, n];

(2)如果正整數t<= 2^k – 1,則t一定能用1,2,4,…,2^(k-1)中某幾個數的和表示,這個很容易證明:我們把t的二進位制表示寫出來,很明顯,t可以表示成 n=a0*2^0+a1*2^1+…+ak*2^(k-1),其中ak=0或者1,表示t的第ak位二進位制數為0或者1.

(3)如果t>=2^k,設s=n-2^k+1,則t-s<=2^k-1,因而t-s可以表示成1,2,4,…,2^(k-1)中某幾個數的和的形式,進而t可以表示成1,2,4,…,2^(k-1),s中某幾個數的和(加數中一定含有s)的形式。

(證畢!)

for

i: 1..n

forj: sum/2

.. w[i]

dp[j]

=max(dp[j], dp[j

-w[i]]

+w[i]);

**:

#include 

<

iostream

>

#include

<

cstdio

>

#include

<

cstring

>

using

namespace

std;

const

intn

=120007

;int

num[6];

intw[n], dp[n];

intmain()

intk =0

; sum

>>=1;

for(i =0

; i

<

6; i

++)

//利用二進位制思想壓縮成0-1揹包問題

w[k++] =

num[i]*(i

+1);}

for(i =0

; i

<

k; i

++)

for(j

=sum; j

>=

w[i]; j--)

dp[j]

=max(dp[j], dp[j

-w[i]]

+w[i]);

//0-1揹包

if(dp[sum]

==sum)

//總數的1/2可達。

printf(

"can be divided.\n\n");

else

printf(

"can't be divided.\n\n");

}return0;

}

部分揹包 poj1014 Dividing

一種物品,限制了數量,那就不能按照完全揹包的寫法去寫了 如果按照01揹包的方法去寫,如果數量很大,那麼必然會超時,那有沒有什麼好辦法呢?我們先講神奇的二進位制思想 我們都知道,任何乙個十進位制都能轉換成二進位制 廢話 那麼二進位制就會對應著許多二進位 還是廢話 每個二進位都是2的倍數 肯定啊 所以反...

POJ 1014 Dividing 母函式優化

description 每一行輸入6個數,第i個數表示價值為i的珠寶的個數,問這些珠寶是不是能等價平分給兩個人。sample input 1 0 1 2 0 0 1 0 0 0 1 1 0 0 0 0 0 0 sample output collection 1 can t be divided.c...

POJ 1014 Dividing(深搜 剪枝)

考慮值為6的石頭 將值為6的石頭分為兩部分,一部分均分為兩堆,另一部分用於填補缺口。所謂填缺口就是當其他的石頭分完之後再把這部分石頭分入兩堆 也有可能只放入一堆 現在考慮需要多少6值石頭用於填缺口。假設左邊的總值小於右邊的總值 1.要能均分,剩下的缺口一定是6的倍數 2.在分配其他的石頭時,可以做到...