题目链接:https://vjudge.net/problem/POJ-2392
贪心的想,先堆限高低的木块,再堆限高更高的木块的方案是更优的,因为反之有可能限高低的木块无法堆.于是将木块按限高排序,然后做多重背包。有两个小优化:
1)如果当前的dp[j]=1,说明当前高度j已经可以由之前的木块堆出,直接continue;
2)如果再循环k(k=1~w[i].c)的时候,发现存在dp[j-k*w[i].h]=1,直接更新dp[j]=1后break,因为当前的高度已经可以被堆出
#include<cstring> using namespace std; const int maxw=40000+10; const int maxn=400+10; struct node{ int h,a,c; }; node w[maxn]; int dp[maxw]; int n,i,j,k,t,ans,m; bool cmp(node p,node q){ if (p.a==q.a) return (p.h<q.h); else return (p.a<q.a); } int main(){ //freopen("poj2392.txt","r",stdin); cin>>n; for (i=1;i<=n;i++) cin>>w[i].h>>w[i].a>>w[i].c; sort(w+1,w+n+1,cmp); memset(dp,0,sizeof(dp)); dp[0]=1; for (i=1;i<=n;i++){ for (j=w[i].a;j>=0;j--) { if (dp[j]) continue; for (k=1;k<=w[i].c;k++) if (j>=k*w[i].h) if (dp[j-k*w[i].h]){ dp[j]=1;break; } } } for (ans=40000;ans>=0;ans--) if (dp[ans]) break; cout<<ans<<endl; //fclose(stdin); return 0; }