多重揹包:
多重揹包問題:給定n
種物品和乙個容量為
v的揹包,第
i種物品的質量為
weight[i]
,價值為
value[i]
,數量是
num[i]
件。可以任意選擇裝入揹包的物品,求裝入揹包中物品的總價值。
這種問題和完全揹包一樣,可以直接套用01
揹包的動態規劃實現,可是很明顯效率太低,時間複雜度並沒有減少。
這裡我們著重講一下如何採用二進位制劃分的方法把多重揹包拆分成幾件物品。思考一下,為什麼我們生活中的紙幣面額是分為1元,5
元,10
元,20
元,50
元,100
元呢?那就是因為這些面額可以湊成 1到
100間的任意整數面額的錢,而如果你只有
1元這種面額,對於
100元就得拿出
100張,太過於麻煩。這種思想完全可以應用到這道題上!
同理,我們不需要把多重揹包裡的第i
件物品都拆分成
num[i]
件,經過證明,我們可以按照二進位制的拆分使件數達到最小。對於第
i件物品,我們把它拆分成1,
2, 4, …,2^t, num[i]-2^(t+1)+1 【t 的範圍: 2^(t+1)<=num[i]<2^(t+2) 】
,就可以滿足要求了。然後我們就把問題再次轉化為了
01揹包求解。
注意,我們之所以用二進位制拆分,是因為其能保證對於0
…num[i]
間的每乙個整數,均可以用若干個係數的和表示。
具體寫**的時候,這裡還有乙個優化的技巧。這裡不再多說,詳細請看**。
-- 多重揹包01
#include #include #include #include #include #include #include typedef long long ll;
using namespace std;
const int maxn = 30 + 10;
const int maxm = 500 + 10;
const int inf = 1;
int n, v;
int weight[maxn], value[maxn], num[maxn];
int dp[maxm];
void zero(int nweight, int nvalue) //01揹包——逆序
void all(int nweight, int nvalue) //完全揹包——順序
void solve()
zero(ncount*weight[i], ncount*value[i]);
} }cout<>n>>v )
return 0;
}
HDU 2199 多重揹包轉化為01揹包
現在假設你一共有資金n元,而市場有m種大公尺,每種大公尺都是袋裝產品,其 不等,並且只能整袋購買。請問 你用有限的資金最多能採購多少公斤糧食呢?輸入資料首先包含乙個正整數c,表示有c組測試用例,每組測試用例的第一行是兩個整數n和m 1 n 100,1 m 100 分別表示經費的金額和大公尺的種類,然...
(部落格搬遷)二維多重揹包轉化為01揹包
題意 有n種物品,每件物品的價值為pr i 體積為v i 重量為w i 數量為c i 現有乙個體積為v,最大可承受重量為w的揹包。問 怎麼樣選擇物品,使得揹包中的物品價值最大?分析 這題其實與上一題差不多,思路是一樣的,只是多了一維,相應的記錄陣列也多一維就搞定。仍然是以二進位制的思想來進行優化。不...
揹包 01揹包,完全揹包,多重揹包
哈哈 01揹包 f i v max 完全揹包 f i v max 多重揹包 f i v max include include include include include define maxn 1000 using namespace std int n,cap int w maxn 重量 花...