转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
多重背包,但是每一个物品有容量限制。
N个柱子,每个柱子有高度,但是有海拔限制。
所有柱子的容量限制可以求出,就是所有限制的最大值。
对于每一个物品改变上界,直接多重背包,然后果断样例都出不了。
只有先计算限制小的,然后再算限制大的,这样才能保证在计算后者的时候利用上前者,保证最优
#include<iostream> #include<iomanip> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> #include<map> #include<stack> #include<set> #include<queue> #include<string> #include<vector> #define eps 1e-6 #define LL long long #define LD long double #define pi acos(-1.0) #define inf 1<<30 using namespace std; struct Node{ int cnt,cost,limit; }a[405]; bool cmp(Node n1,Node n2){ return n1.limit<n2.limit; } int dp[40005],n,m; void zeroonepack(int val,int cost,int limit){ for(int i=limit;i>=cost;i--) dp[i]=max(dp[i],dp[i-cost]+val); } void completepack(int val,int cost,int limit){ for(int i=cost;i<=limit;i++) dp[i]=max(dp[i],dp[i-cost]+val); } void doublepack(int cost,int val,int count,int limit){ if(cost*count>=limit) completepack(val,cost,limit); else{ int tmp=1; while(tmp<=count){ zeroonepack(val*tmp,cost*tmp,limit); count-=tmp; tmp<<=1; } if(count) zeroonepack(val*count,cost*count,limit); } } int main(){ while(scanf("%d",&n)!=EOF){ m=0; for(int i=0;i<n;i++){ scanf("%d%d%d",&a[i].cost,&a[i].limit,&a[i].cnt); m=max(m,a[i].limit); } memset(dp,0,sizeof(dp)); sort(a,a+n,cmp); for(int i=0;i<n;i++) doublepack(a[i].cost,a[i].cost,a[i].cnt,a[i].limit); int ans=0; for(int i=0;i<=m;i++) ans=max(ans,dp[i]); printf("%d\n",ans); } return 0; }