大家好,又见面了,我是全栈君。
多重背包问题。
我的背包训练第三题,多重背包。
似乎有点理解多重背包了。
我对背包九讲多重背包的理解:
当某件物品 体积*数量 超过背包的容积的时候,这就做全然背包(相当于无限取)
void completepack(int h,int cost,int a) { for(int i=cost;i<=a;i++) dp[i]=max(dp[i],dp[i-cost]+h); }
而某件物品有多件却不能装满背包的时候,一件一件的来做01背包 太浪费。然后採取二进制的办法,每次乘2。
把每次乘2 的 来做一次01 背包。
这样时间复杂度减少 。
void zeroonepack(int h,int cost,int a) { for(int i=a;i>=cost;i--) dp[i]=max(dp[i],dp[i-cost]+h); }
这样分开然后再分解。让多重背包就简单起来了。
void multiplepack(int h,int cost,int c,int a) { if(cost*c>=a) { completepack(h,cost,a); return; //相当于做一次全然背包 } int k=1; while(k<c) { zeroonepack(h*k,cost*k,a); c-=k; k*=2; //多次01背包 } zeroonepack(h*c,cost*c,a); }
AC 代码:
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<queue> #include<map> #include<stack> #include<iostream> #include<list> #include<set> #include<cmath> #define INF 0x7fffffff #define eps 1e-6 #define LL long long using namespace std; int dp[40001]; int n; struct lx { int h,c,a; }l[401]; bool cmp(lx a,lx b) { return a.a<b.a; } void zeroonepack(int h,int cost,int a) { for(int i=a;i>=cost;i--) dp[i]=max(dp[i],dp[i-cost]+h); } void completepack(int h,int cost,int a) { for(int i=cost;i<=a;i++) dp[i]=max(dp[i],dp[i-cost]+h); } void multiplepack(int h,int cost,int c,int a) { if(cost*c>=a) { completepack(h,cost,a); return; } int k=1; while(k<c) { zeroonepack(h*k,cost*k,a); c-=k; k*=2; } zeroonepack(h*c,cost*c,a); } int main() { while(scanf("%d",&n)!=EOF) { int m=0; for(int i=0;i<n;i++) { scanf("%d%d%d",&l[i].h,&l[i].a,&l[i].c); m=max(m,l[i].a); } memset(dp,0,sizeof(dp)); sort(l,l+n,cmp); for(int i=0;i<n;i++) { multiplepack(l[i].h,l[i].h,l[i].c,l[i].a); } int ans=0; for(int i=0;i<=m;i++) //printf("%d =\n",dp[i]); ans=max(ans,dp[i]); printf("%d\n",ans); } }
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116608.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...