多重背包介于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 ",dp[n]); 49 } 50 return 0; 51 }