标签:-- roo 多重背包 let log 不同 col number 完全
题意;输入数据首先包含一个正整数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]); } }
标签:-- roo 多重背包 let log 不同 col number 完全
原文地址:https://www.cnblogs.com/Tianwell/p/11218204.html