珍惜现在,感恩生活 (多重背包)
Posted tianwell
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了珍惜现在,感恩生活 (多重背包)相关的知识,希望对你有一定的参考价值。
题意;输入数据首先包含一个正整数C,表示有C组测试用例 每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100) 分别表示经费的金额和大米的种类,然后是m行数据,
每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20) 分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。 求能得到的最大重量多重背包
思路:这是一道很模板的多重背包
所以我就对多重背包的dp思路总结一下:
事实上多重背包问题可以看作0/1背包和完全背包的总和
比如给出一个物品 体积w[i] , 数量num[i] , 如果 w[i]*num[i] >= N(总的背包体积/或者余下的体积),那么意味着 我可以随便取这个物品,直到背包装满 或者塞不下这个物品
如果w[i]*num[i] <N ,那么我们就只能取(1~ num[i])个这个物品 ,我们假设其为 num[i]个不同的物品但是其w和v相同 ,然后一个一个取 (所以此时就转化为0/1背包)
当然我们在一个一个取时可以相对优化一下 采用二进制的思想 更快速的取完这个物品
下面这个代码是转用别人的模板我觉得对理解很有意义:https://blog.csdn.net/qq_38984851/article/details/81133840
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define MAX 1000000 using namespace std; int dp[MAX];//存储最后背包最大能存多少 int value[MAX],weight[MAX],number[MAX];//分别存的是物品的价值,每一个的重量以及数量 int bag; void ZeroOnePack(int weight,int value )//01背包 int i; for(i = bag; i>=weight; i--) dp[i] = max(dp[i],dp[i-weight]+value); void CompletePack(int weight,int value)//完全背包 int i; for(i = weight; i<=bag; i++) dp[i] = max(dp[i],dp[i-weight]+value); void MultiplePack(int weight,int value,int number)//多重背包 if(bag<=number*weight)//如果总容量比这个物品的容量要小,那么这个物品可以直到取完,相当于完全背包 CompletePack(weight,value); return ; else//否则就将多重背包转化为01背包 int k = 1; while(k<=number) ZeroOnePack(k*weight,k*value); number = number-k; k = 2*k;//这里采用二进制思想(二进制与十进制的转化)(快速幂也是这个思路) //而不是一个一个的减 ZeroOnePack(number*weight,number*value); int main() int t; cin>>t; while(t--) int n; while(~scanf("%d%d",&bag,&n)) int i,sum=0; for(i = 0; i<n; i++) scanf("%d",&weight[i]); scanf("%d",&value[i]);//输入价值 此题没有物品的重量,可以理解为体积和价值相等 scanf("%d",&number[i]);//输入数量 memset(dp,0,sizeof(dp)); for(i = 0; i<n; i++) MultiplePack(weight[i],value[i],number[i]);//调用多重背包,注意穿参的时候分别是 //重量,价值和数量 cout<<dp[bag]<<endl; return 0;
然后这是另一种思路的代码:(就是尝试对每一种都一个一个取)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int v[110],w[110],ans[110],dp[110][110]; int main() int t,n,m,i,j,k; scanf("%d",&t); while(t--) scanf("%d%d",&m,&n); //m是经费,n种大米 for(i=0;i<n;i++) scanf("%d%d%d",&w[i],&v[i],&ans[i]);//w价格,v是每袋的重量,ans是袋数 memset(dp,0,sizeof(dp)); //初始化 for(i=0;i<n;i++) //n种大米 for(j=0;j<=m;j++) //剩余j元最多能买多少 if(j<w[i]) //剩余的钱不能买这一袋 dp[i+1][j]=dp[i][j]; else for(k=0;k<=ans[i]&&w[i]*k<=j;k++) //这种大米,从买0袋开始尝试买多少 dp[i+1][j]=max(dp[i+1][j],dp[i][j-k*w[i]]+k*v[i]); // 原本的花费 这种大米买k袋 printf("%d\n",dp[n][m]);
以上是关于珍惜现在,感恩生活 (多重背包)的主要内容,如果未能解决你的问题,请参考以下文章
悼念512汶川大地震遇难同胞——珍惜现在,感恩生活--hdu2191(多重背包模板)
HDU2191悼念512汶川大地震遇难同胞——珍惜现在,感恩生活[多重背包]
hdu-2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活---多重背包