Problem Description
急!灾区的食物依然短缺! 为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。 请问:你用有限的资金最多能采购多少公斤粮食呢? 后记: 人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。 月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活—— 感谢父母,他们给予我们生命,抚养我们成人; 感谢老师,他们授给我们知识,教我们做人 感谢朋友,他们让我们感受到世界的温暖; 感谢对手,他们令我们不断进取、努力。 同样,我们也要感谢痛苦与艰辛带给我们的财富~
Input
输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。
Output
对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。
Sample Input
1
8 2
2 100 4
4 100 2
Sample Output
400
Author
lcy
比较直白的(数据较小):
1 #include2 #include 3 #include 4 using namespace std; 5 6 int c[105], w[105], n[105]; 7 int bag[105]; 8 int N, V; 9 10 void _mul_bag() //多重背包:直接转换成01背包(数据比较小)11 {12 int i, j, k;13 memset(bag, 0, sizeof(bag));14 for(i = 0; i < N; i++)15 {16 for(k = 1; k <= n[i]; k++)17 {18 for(j = V; j >= c[i]; j--)19 {20 bag[j] = max(bag[j], bag[j-c[i]] + w[i]);21 }22 }23 }24 }25 26 int main()27 {28 int i, t;29 scanf("%d", &t);30 while(t--)31 {32 scanf("%d %d", &V, &N);33 for(i = 0; i < N; i++)34 scanf("%d %d %d", &c[i], &w[i], &n[i]);35 _mul_bag();36 printf("%d\n", bag[V]);37 }38 39 return 0;40 }
二进制优化:
1 在这之前,我空间好像转过一个背包九讲,现在我就只对 2 01背包和多重背包有点印象了 3 4 先说下 01 背包,有n 种不同的物品,每个物品有两个属性 5 size 体积,value 价值,现在给一个容量为 w 的背包,问 6 最多可带走多少价值的物品。 7 8 int f[w+1]; //f[x] 表示背包容量为x 时的最大价值 9 for (int i=0; i=size[i]; j++) 11 f[j] = max(f[j], f[j-size[i]]+value[i]); 12 13 如果物品不计件数,就是每个物品不只一件的话,稍微改下即可 14 for (int i=0; i < <右移 相当于乘二 54 value[count]="k*v;" 55 size[count++]="k*s;" 56 c -="k;" 57 } 58 if (c> 0) { 59 value[count] = c*v; 60 size[count++] = c*s; 61 } 62 } 63 64 现在用count 代替 n 就和01 背包问题完全一样了 右移>
背包九讲里面,他的实现方法和这个是不一样的,利用01背包和完全背包来配合实现的,下面是实现:
1 /* 2 HDOJ 2191 3 多重背包用二进制转化的思想,进行优化 4 */ 5 6 #include7 using namespace std; 8 9 int weight[110],Value[110],num[110]; 10 int f[1100]; 11 int limit; 12 13 inline void ZeroOnePack(int w,int v) 14 { 15 int j; 16 for(j=limit;j>=w;j--) 17 { 18 if(f[j-w]+v > f[j]) 19 f[j]=f[j-w]+v; 20 } 21 } 22 23 inline void CompletePack(int w,int v) 24 { 25 int j; 26 for(j=w;j<=limit;j++) 27 { 28 if(f[j-w]+v > f[j]) 29 f[j]=f[j-w]+v; 30 } 31 } 32 33 inline void MultiplePack(int w,int v,int amount) 34 { 35 if(amount * w >= limit) 36 { 37 CompletePack(w,v); 38 return ; 39 } 40 for(int k=1;k <<=1) 41 { 42 ZeroOnePack(k*w,k*v); 43 amount -= k; 44 } 45 ZeroOnePack(amount*w,amount*v); 46 } 47 48 int main() 49 { 50 int T,n; 51 cin>>T; 52 while(T--) 53 { 54 cin>>limit>>n; 55 56 for(int i=0;i >weight[i]>>Value[i]>>num[i]; 58 59 memset(f,0,sizeof(f)); 60 61 for(i=0;i
1 #include2 #include 3 #include 4 using namespace std; 5 int t,v,n; 6 int c[109],w[109],num[109],F[109]; 7 8 void zeroonebag(int cost,int weight){ 9 for(int i=v;i >= cost;i--) F[i]=max(F[i],F[i-cost]+weight);10 }11 12 void completebag(int cost,int weight){13 for(int i=cost;i <= v;i++) F[i]=max(F[i],F[i-cost]+weight);14 }15 16 void multiplybag(int cost,int weight,int num){17 if(cost*num >= v) completebag(cost,weight);18 else{19 int k=1,m=num;20 while(k < m){21 zeroonebag(k*cost,k*weight);22 m-=k;23 k*=2;24 }25 zeroonebag(m*cost,m*weight);26 }27 }28 29 int main(void){30 scanf("%d",&t);31 while(t--){32 scanf("%d%d",&v,&n);33 for(int i=0;i < n;i++) scanf("%d%d%d",&c[i],&w[i],&num[i]);34 memset(F,0,sizeof(F));35 for(int i=0;i < n;i++) multiplybag(c[i],w[i],num[i]);36 printf("%d\n",F[v]);37 }38 return 0;39 }
单调队列:http://www.cppblog.com/flyinghearts/archive/2010/09/01/125555.aspx
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 using namespace std; 8 int dp[102]; 9 int p[102],h[102],c[102];10 int n,m;11 void comback(int v,int w)//经费,重量。完全背包;12 {13 for(int i=v; i<=n; i++)14 if(dp[i] =v; i--)20 if(dp[i] =n) comback(p[i],h[i]);35 else36 {37 for(j=1; j