Space Elevator POJ 2392(多重背包dp)
原题
题目分析
多重背包题,在放入的时候需要按a的大小排序.定义dp[i][j]为前i个积木凑成j高度,第i个物品最多剩下多少,然后j从0遍历到a[i],dp初始化为-1,dp[0][0]=0.更新方式跟多重背包完全一样,if(dp[i-1][j]!=-1) dp[i][j]=c[i];else if(j>=h[i]&&dp[i][j-h[i]]>0) dp[i][j]=dp[i][j-h[i]]-1;由更新方向可知可以状压,把第一维压掉,第二维j从小到大遍历即可.最后从dp数组中找一个最大的j即为答案.
代码
1 #include <iostream> 2 #include <algorithm> 3 #include <utility> 4 #include <cstdio> 5 #include <cmath> 6 #include <cstring> 7 #include <string> 8 #include <vector> 9 #include <stack> 10 #include <queue> 11 #include <map> 12 #include <set> 13 14 using namespace std; 15 typedef long long LL; 16 const int INF_INT=0x3f3f3f3f; 17 const LL INF_LL=0x3f3f3f3f3f3f3f3f; 18 19 struct N 20 { 21 int h,a,c; 22 }block[500]; 23 24 bool cmp(N x,N y) 25 { 26 return x.a<y.a; 27 } 28 29 int dp[50000]; 30 31 int main() 32 { 33 // freopen("black.in","r",stdin); 34 // freopen("black.out","w",stdout); 35 int k; 36 cin>>k; 37 for(int i=1;i<=k;i++) cin>>block[i].h>>block[i].a>>block[i].c; 38 sort(block+1,block+1+k,cmp); 39 // for(int i=1;i<=k;i++) printf("block %d h=%d a=%d c=%d\n",i,block[i].h,block[i].a,block[i].c); 40 for(int j=0;j<=block[k].a;j++) dp[j]=-1; 41 for(int i=1;i<=k;i++) 42 { 43 dp[0]=block[i].c; 44 for(int j=1;j<=block[i].a;j++) 45 { 46 if(dp[j]!=-1) dp[j]=block[i].c; 47 else if(j>=block[i].h&&dp[j-block[i].h]>0) dp[j]=dp[j-block[i].h]-1; 48 } 49 // for(int j=0;j<=block[].a;j++) printf("dp %d %d=%d\n",i,j,dp[j]); 50 } 51 int ans=block[k].a; 52 while(dp[ans]==-1) ans--; 53 cout<<ans<<endl; 54 return 0; 55 }