dividing
題意:有一堆大理石,每個石頭的價值在1-6之間,每種**的石頭有多個。現在要求將這堆石頭分成兩份,使得兩份的總價值相同,回答是否存在一種方法將可以實現劃分。
這是一道多重揹包問題,多重揹包問題的做法可以是先將它轉化為01揹包,再用01揹包問題的方法繼續求解。轉化的思路是,將乙個**下的幾件物品,組合成多個**下個一件物品。比如**2下原來有7件物品(二進位制111),可以分為有1件**1的物品(001),1件**2的物品(010),1件**4的物品(100),可以看出這裡用到了二進位制的操作。 這麼操作能夠實現每種物品只有乙個,只有1拿和0不拿兩種情況。且可以組合成原多重揹包時的任意組合。
程式中,t[i]表示有價值i的大理石數量,現在要把他分成編號1-count-1的大理石w[i]記錄編號i的大理石的價值,轉化後,每個編號下的物品只有乙個。
for(int i=1;i<=6;i++)
w[count]=t[i]*i;
count++;
}
本題與常見的01揹包略有不同的是,本題沒有物品的體積,所以可以當作物品的體積和價值一樣來做。狀態轉移方程就是,dp[i][j] = max( dp[i][j-w[i]]+w[i] , dp[i-1][j] ),做題時再把dp陣列壓縮成一維,便有了如下的程式
for(int i=1;i<=count-1;i++)
}
看到了部落格經典揹包問題 01揹包+完全揹包+多重揹包寫得不錯,引用一下,可以當作模板的兩個**
01 揹包
有n 種不同的物品,每個物品有兩個屬性,
size 體積,value 價值,現在給乙個容量為 w 的揹包,問
最多可帶走多少價值的物品。
int f[w+1]; //f[x] 表示揹包容量為x 時的最大價值
for (int i=0; i=size[i]; j--)
f[j] = max(f[j], f[j-size[i]]+value[i]);
完全揹包
如果物品不計件數,就是每個物品不只一件的話,稍微改下即可
for (int i=0; i
最後是我ac的完整**
#include#include#includeusing namespace std;
int t[10],dp[140010],w[140010];
int dp_fun(int sum)
w[count]=t[i]*i;
count++; }
for(int i=1;i<=count-1;i++) }
return dp[sum];
}int main()
} if(flag == 0)
cout << "collection #"<
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 ...