多重背包介於0-1背包和完全背包之間:有容積為V的背包給定一些物品,每種物品包含體積w,價值v和數量k,求用該背包能
裝下的最大價值總量。可以將多重背包問題直接轉化到0-1背包上去,即將每種物品被均視為k種不同的物品。
0-1背包的介紹可見另一博文 http://www.cnblogs.com/yuxiaoba/p/8458135.html
完全背包介紹可見另一博文 http://www.cnblogs.com/yuxiaoba/p/8458447.html
可以采取一種技巧性地拆分,將原數量為k的物品拆分為若干組,每組物品看成一件物品,其價值和重量為該組中所有物品的
價值重量總和,每組物品包含的原物品個數分別為:1、2、4、……k-2^c+1, 其中c為使 k-2^c+1大於0的最大整數。這種類似於二進制的拆分,不僅可以將物品數量大大降低,同時通過對這些若干原物品組合得到的新物品的不同組合,可以得到0到k之間任意件物品的價值重量和。
珍惜現在,感恩生活
題目描述
急!災區的食物依然短缺!
為了挽救災區同胞的生命,心系災區同胞的你准備自己采購一些糧食支援災區,現在假設你一共有資金n元,而市場有m種大米,每種大米都是袋裝產品,其價格不等,並且只能整袋購買。
請問:你用有限的資金最多能采購多少公斤糧食呢?
為了挽救災區同胞的生命,心系災區同胞的你准備自己采購一些糧食支援災區,現在假設你一共有資金n元,而市場有m種大米,每種大米都是袋裝產品,其價格不等,並且只能整袋購買。
請問:你用有限的資金最多能采購多少公斤糧食呢?
輸入描述:
輸入數據首先包含一個正整數C,表示有C組測試用例,每組測試用例的第一行是兩個整數n和m(1<=n<=100, 1<=m<=100),分別表示經費的金額和大米的種類,然后是m行數據,每行包含3個數p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分別表示每袋的價格、每袋的重量以及對應種類大米的袋數。
輸出描述:
對於每組測試數據,請輸出能夠購買大米的最多重量,你可以假設經費買不光所有的大米,並且經費你可以不用完。每個實例的輸出占一行。
示例1
輸入
1 8 2 2 100 4 4 100 2
輸出
400
1 #include <stdio.h> 2 #include <limits.h> 3 4 int max( int a,int b) 5 { 6 return a > b ? a:b; 7 } 8 9 struct E 10 { 11 int w; //大米價格 12 int v; //大米重量 13 } list[2001]; 14 int dp[101]; 15 16 int main() 17 { 18 int T,n,m; 19 int p,h,k; 20 int i,j; 21 int index,c; 22 scanf("%d",&T); 23 24 while( T-- ) 25 { 26 scanf("%d%d",&n,&m); 27 index = 0; //拆分后物品總數 28 for( i=1; i<=m; i++) 29 { 30 c = 1; 31 scanf("%d%d%d",&p,&h,&k); 32 while( k-c>0) 33 { 34 k -= c; 35 list[++index].w = c*p; 36 list[index].v = c*h; 37 c *= 2; 38 } 39 list[++index].w = p*k; //補充不足指數的差值 40 list[index].v = h*k; 41 } 42 for( i=0; i<=n; i++) dp[i]=0; 43 for( i=1; i<=index; i++) //對拆分后的物品進行0-1背包 44 { 45 for( j=n; j>=list[i].w; j--) 46 dp[j] = max( dp[j],dp[j-list[i].w]+list[i].v); 47 } 48 printf("%d\n",dp[n]); 49 } 50 return 0; 51 }