前面的01揹包問題中,每種商品(物品)只有一件,而當遇到每種物品超過一件的情況叫做多重揹包問題。
下面請看這道程式設計題:
有 n 種物品和乙個容量是 v 的揹包。
第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi。
求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。
輸出最大價值。
輸入格式
第一行兩個整數,n,v,用空格隔開,分別表示物品種數和揹包容積。
接下來有 n 行,每行三個整數 vi,wi,si,用空格隔開,分別表示第 i 種物品的體積、價值和數量。
輸出格式
輸出乙個整數,表示最大價值。
資料範圍
0輸入樣例
4 51 2 3
2 4 1
3 4 3
4 5 2
輸出樣例:
10
通常,我們的思路是把多重揹包問題轉化為01揹包問題來做,首先想到的就是將多個重複的商品攤開來形成多個體積和價值都相同的商品,然後使用01揹包問題解決。但是在這道題中,注意商品數n和每件商品的重複測試上限均超過1000,因而如果使用上述方法轉換則會使複雜度達到1000*2000*2000 = 4*10^9
,因而肯定會超時,下面給出我寫出的以上思路的**以供參考。
#include #include #include using namespace std;
int main()}}
vector> objectv(numin,vector(numvolume)); //建立乙個二維矩陣,存放滿足條件的最大價值遞推矩陣
int count = 0;
for(int j=0;j本人程式設計能力有限,**實現的有點長,弄了半天還超時了,沒有通過全部測試。因而要解決這個問題必須考慮一些優化方法。
下面介紹本題的改進方法,二進位制優化方法。
在本題中,如果能把s個i物品分解成一些不重複的幾個i物品的組合就好了。即將乙個數si分解成p個數,要求這p個數的任意組合可以組成比這個數小的任意數(0~si),求p的最小值是多少?
將乙個數si分解成p個數,要求這p個數的任意組合可以組成比這個數小的任意數(0~si),求p的最小值是多少?我們可以發現當si = 0的時候,p=0;(p= log1)
si = 1, p=1; (1) (p = log2)
si = 2, p=2; (1,2) (p=[log3])
si = 3, p=2; (1,2) (p = log4)
si = 4, p=3; (1,2,3) (p=[log5])
...其中表示向上取整。
因而對於si件物品i,最小可以分解成[log(si+1)]件物品,因而減少了分解後物品的數目,從而可以提高運算效率。
依據以上思想進行程式設計,**如下:
#include #include #include using namespace std;
struct good;
int main();
int n, m; //分別表示物品種數和揹包容量
cin >> n >> m;
for(int i = 0; i < n; i++));
}if(s > 0));}}
for(auto go : goods)
}cout << f[m];
return 0;
}
以上**的執行時間363ms,滿足要求。 多維多重揹包問題 多重揹包問題
悼念512汶川大 遇難同胞 珍惜現在,感恩生活 急!災區的食物依然短缺!為了挽救災區同胞的生命,心繫災區同胞的你準備自己採購一些糧食支援災區,現在假設你一共有資金n元,而市場有m種大公尺,每種大公尺都是袋裝產品,其 不等,並且只能整袋購買。請問 你用有限的資金最多能採購多少公斤糧食呢?後記 人生是乙...
揹包問題 多重揹包
有n種物品和乙個容量為w的揹包。第i種物品最多有n i 件可用,每件重量是w i 價值是v i 求解將哪些物品裝入揹包可使這些物品的重量總和不超過揹包容量,且價值總和最大。1.使用三重迴圈進行遞推 狀態轉移式為 dp i j max 關鍵 如下 void solve printf d n dp n ...
多重揹包問題
有n種物品和乙個容量為v的揹包。第i種物品最多有n i 件可用,每件費用是c i 價值是w i 求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。這題目和完全揹包問題很類似。基本的方程只需將完全揹包問題的方程略微一改即可,因為對於第i種物品有n i 1種策略 取0件,取1件...