這題做了將近乙個月,斷斷續續的看揹包問題,今天總於一口氣把揹包九講中的前三講看完了。
為什麼這樣正確呢?
證明:(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)的形式。
(證畢!)
fori: 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.在分配其他的石頭時,可以做到...