Codeforces 864E - Fire(dp)
原题连接:http://codeforces.com/problemset/problem/864/E
题意:一个人想从大火中带走一些东西。每次他只能带一个,耗时ti ,价值为pi, 当总时间超过di时不能被带走。问他如何按顺序带走物品使价值总和最大。
思路:背包问题。分为取和不取两种情况1.dp[i][j]=max(dp[i-1][j], dp[i-1][j-t]+p), j<d;
2.dp[i][j]=max(dp[i-1][j], dp[i][j]);
AC代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 struct G{ 8 int t,d,v; 9 int id; 10 }g[105]; 11 int dp[105][2005]; 12 bool vis[105][2005]; 13 bool cmp(G a, G b){ 14 return a.d<b.d; 15 } 16 int main() 17 { 18 int n,maxx=0; 19 scanf("%d", &n); 20 memset(dp, 0, sizeof(dp)); 21 memset(vis, 0, sizeof(vis)); 22 for(int i=1;i<=n;i++){ 23 scanf("%d %d %d", &g[i].t, &g[i].d, &g[i].v); 24 g[i].id=i; 25 maxx=max(maxx, g[i].d); 26 } 27 sort(g+1, g+n+1, cmp); 28 int b; 29 for(int i=1;i<=n;i++){ 30 b=0; 31 for(int j=0;j<=maxx;j++){ 32 if(j>=g[i].t&&j<g[i].d&&dp[i-1][j]<dp[i-1][j-g[i].t]+g[i].v){ 33 dp[i][j]=dp[i-1][j-g[i].t]+g[i].v; 34 vis[i][j]=1; 35 } 36 else dp[i][j]=dp[i-1][j]; 37 if(dp[i][j]>=dp[i][b]) b=j; 38 } 39 } 40 printf("%d\n", dp[n][b]); 41 vector<int> ans; 42 for(int i=n;i;i--){//反推,得到最优取法 43 if(vis[i][b]){ 44 ans.push_back(g[i].id); 45 b-=g[i].t; 46 } 47 } 48 printf("%d\n", ans.size()); 49 for(int i=ans.size()-1;i>=0;i--) printf("%d ",ans[i]); 50 return 0; 51 }