hdu1059 Dividing 多重揹包

2021-06-29 12:49:58 字數 2026 閱讀 4303

題意:將價值分別為1,2,3,4,5,6的6種多個物品平均分兩坨

所有物品數量加起來不超過2w個

很容易想到dp的思路,dp[i]表示是否存在使價值為i的選法,dp[i]=dp[i-j] j為物品的價值。然後對所有物品進行這種迴圈即可,但是會超時,這時候就需要將大量的相同物品二進位制分割,具體的原理需要用心去感受,這是揹包九講中的原文:

方法是:將第i種物品分成若干件物品,其中每件物品有乙個係數,這件物品的費用和價值均是原來的費用和價值乘以這個係數。使這些係數分別為 1,2,4,…,2^(k-1),n[i]-2^k+1,且k是滿足n[i]-2^k+1>0的最大整數。例如,如果n[i]為13,就將這種 物品分成係數分別為1,2,4,6的四件物品。

分成的這幾件物品的係數和為n[i],表明不可能取多於n[i]件的第i種物品。另外這種方法也能保證對於0..n[i]間的每乙個整數,均可以用若干個係數的和表示,這個證明可以分0..2^k-1和2^k..n[i]兩段來分別討論得出,並不難,希望你自己思考嘗試一下。

這樣就將第i種物品分成了o(log n[i])種物品,將原問題轉化為了複雜度為o(v*σlog n[i])的01揹包問題,是很大的改進。

下面給出o(log amount)時間處理一件多重揹包中物品的過程,其中amount表示物品的數量:

procedure

multiplepack

(cost,weight,amount)

ifcost*amount>=v

completepack

(cost,weight)

return

integer

k=1 while

kzeroonepack

(k*cost,k*weight)

amount=amount-k

k=k*2

zeroonepack

(amount*cost,amount*weight)

希望你仔細體會這個偽**,如果不太理解的話,不妨翻譯成程式**以後,單步執行幾次,或者頭腦加紙》筆模擬一下,也許就會慢慢理解了。

揹包的上限空間是總價值/2 ,背完後看看dp[總價值/2]是不是true即可。

貼**。value開100是因為經過二進位制分割之後粗略算一下不會有超過100個物品。

#include 

#include

#include

#include

#include

#include

#include

#include

#define ninf int_min

#define ll long long

using

namespace

std;

//用多重揹包的方法,將一坨一樣的珠寶變成乙個乙個不一樣的

int value[100];

int total;

int totalvalue;

bool dp[61111];

//dp[i]為true表示存在分出i的價值的方法

int main()

if (tmp)

value[total++]=tmp*i;

}if (totalvalue&1)

//要求剛好分一半 即揹包剛好裝滿,對於最開始的狀態,沒有乙個物品的情況下除了0空間之外其他都是非法的

memset(dp,0,sizeof(dp));

dp[0]=true;

for (int i=1;i//i是選擇的物品

for (int j=totalvalue/2;j>=value[i];j--) //j是空間

if (dp[j-value[i]])

dp[j]=true;

if (dp[totalvalue/2])

cout

<<"can be divided."

cout

<<"can't be divided."

0;}

HDU 1059 Dividing(多重揹包)

題意 輸入6個數字,表示重量分別為1 2 3 4 5 6的大理石的數量 問能不能將這些大理石均分,不能把大理石弄破了 能的話就輸出 can be divided.不能就輸出can t be divided.解題思路 邊輸入邊求和 如果和為0,就break 如果和為奇數,就輸出can t be div...

HDU 1059 Dividing 多重揹包

題目就是要分彈珠,一人一半,多乙個少乙個都不行。六種彈珠,ni表示價值i的彈珠的數量,問能不能分。1.總價值為奇數當然不能分了。2.總價值為偶數,利用多重揹包求解,揹包容量為m 2,計算dp m 能否等於m,能就可以分。include includeint val 10 num 10 int dp ...

hdu 1059 Dividing 多重揹包

傳送門 分析 多重揹包按照二進位制拆分為01揹包 假設價值為w的物品有n個,則按照 1,2,4,8,1 log n 拆分 設sum 1,1 log n sum,設 ret n sum 則有在 0 sum 內的所有數p都可以用拆分數的和表示 二進位制表示 而 sum n 之間的數可用 p ret表示 ...