//起初自己没发现需要对限制高度升序排列,,,举了几个例子重要发现要是不先使用限制高度低的补充背包,那么后面的背包可能取不到最优子状态 //如果排好了序,就显然是多重背包了 /* ID:1192432 PROG: castle LANG: C++ */ #include <iostream> #include <queue> #include <stack> #include <string> #include <map> #include <vector> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const int MAXN=405,MAXH=40005,INF=1<<30; struct Block{ int h,lim,c; }; Block a[MAXN]; int n,H; int f[MAXH]; void ZeroOnePack(int cost,int weight,int lim){ for(int h=lim;h>=cost;h--) f[h]=max(f[h],f[h-cost]+weight); return ; } void CompletePack(int cost,int weight,int lim){ for(int h=cost;h<=lim;h++) f[h]=max(f[h],f[h-cost]+weight); return ; } void MultiplyPack(int cost,int weight,int amount,int lim){ if(cost*amount>=H){ CompletePack(cost,weight,lim); return ; } int k=1; while(k<amount){ ZeroOnePack(k*cost,k*weight,lim); amount-=k; k*=2; } ZeroOnePack(amount*cost,amount*weight,lim); return ; } bool cmp(const Block &i,const Block &j){ return i.lim<j.lim; } int main() { #ifndef ONLINE_JUDGE freopen("i.txt", "r", stdin); #endif int ans=-INF; cin>>n; H=-INF; for(int i=1;i<=n;i++){ cin>>a[i].h>>a[i].lim>>a[i].c; H=max(H,a[i].lim); } sort(a+1,a+1+n,cmp); for(int i=0;i<=H;i++) f[i]=-INF; f[0]=0; for(int i=1;i<=n;i++) MultiplyPack(a[i].h,a[i].h,a[i].c,a[i].lim); //for(int i=0;i<=H;i++) cout<<"F:"<<f[i]<<endl; for(int i=0;i<=H;i++) ans=max(ans,f[i]); cout<<ans<<endl; return 0; }