hdu 1059 dividing(多重揹包)
題意
:
如今有價值為1,2,3,4,5,6的6種物品, 它們的數量為num[i]( 1<=i<=6 )個. 如今要問的是是否能把全部的的物品分成兩份且這兩份物品的價值總和同樣 ?
分析
:
首先我們求出全部物品的價值和sum_val, 假設sum_val是奇數, 那麼明顯不能分. 那麼sum_val為偶時, 我們令m=sum_val/2. 我能僅僅要看看從全部物品裡面取物品是否能使得: 「全部取的物品總價值==m?」
因為每乙個物品的數目是num[i]個, 所以本題是乙個多重揹包問題.
事實上多重揹包問題能夠轉成01揹包來解, 可是效率不高. 所以這裡我們按<<
揹包九講
>>中提到的二進位制壓縮的思想來解決本題.
令dp[i][j]==x 表示選前i種物品且總價值<=j的前提下, 全部被選物品能達到的最大價值.
對於val[i]*num[i]>=m的物品來說, 我們直接用一次全然揹包就可以.
即dp[i][j] = max( dp[i-1][j] , dp[i][j-val[i]]+val[i] )
對於val[i]*num[i]
1個 2個 4個… 2^(k-1)個 以及 num[i] – 2^k+1 個
我們對由第i種物品劃分成的上述每堆物品做一次01揹包就可以.
(為什麼上面的劃分能得到正確解
?
由於上面的物品覆蓋了我們對
num[i]個第i
類物品的全部可能選擇)
終於所求: 看dp[n][m]是否等於m就可以.
ac**:
#include#include#includeusing namespace std;
const int maxn=20000+5;
int m;//dp最大不能超過的價值
int dp[maxn*5];
int val=;//每種物品的價值
int num[10]; //每種物品的數量
//一次01揹包過程
void zero_one_pack(int cost,int val)
//一次全然揹包過程
void complete_pack(int cost, int val)
//一次多重揹包過程
void multiple_pack(int cost,int val,int sum)
//log(sum)次01揹包
int k=1;
while(k
hdu1059 Dividing 多重揹包
題意 將價值分別為1,2,3,4,5,6的6種多個物品平均分兩坨 所有物品數量加起來不超過2w個 很容易想到dp的思路,dp i 表示是否存在使價值為i的選法,dp i dp i j j為物品的價值。然後對所有物品進行這種迴圈即可,但是會超時,這時候就需要將大量的相同物品二進位制分割,具體的原理需要...
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 ...