Codeforces Round #436 (Div. 2) E. Fire
http://codeforces.com/contest/864/problem/E
题意:
有一堆物品,每个物品有3个属性,需要的时间,失效的时间(一开始)和价值。只能一件一件的选择物品(即在选择这件物品时需要一定的时间,在这段时间之内不能选择其他物品),选择这件物品只能在失效时间之前选择。问选择的最大价值是多少。
思路:
对于每一个物品,有选和不选两种操作,与01背包是相似的。但是此题选择的顺序会影响到结果,这是01背包不同的地方。
比如 a.st = 3,a.en = 5,a.v = 4
b.st = 4,b.en = 8,b.v = 5
这组数据先选择a,再选择b符合条件,价值最大,但是如果先选择b,那么a就没得选了,所以我们需要按照一定的顺序来选择。
那么通过这个例子可以直观的感受到我们按结束时间排序之后进行选择得到的结果是最优的。
背包的时候,把时间当作体积V,然后滚动数组优化时间就得逆序枚举,时间必须是失效时间-1(因为是在失效时间按之前),然巧妙的用一个vector来保存物品的编号就可以了。
代码:
1 #include <stdio.h> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 6 struct node 7 { 8 int s,e,v; 9 int id; 10 11 void read(void) 12 { 13 scanf("%d%d%d",&s,&e,&v); 14 } 15 } a[105]; 16 17 bool cmp(node aa,node bb) 18 { 19 return aa.e < bb.e; 20 } 21 22 int dp[2005]; 23 vector<int> g[2005]; 24 25 int main() 26 { 27 int n; 28 29 scanf("%d",&n); 30 31 for (int i = 1;i <= n;i++) 32 a[i].read(),a[i].id = i; 33 34 sort(a+1,a+n+1,cmp); 35 36 for (int i = 1;i <= n;i++) 37 { 38 for (int j = a[i].e - 1;j >= a[i].s;j--) 39 { 40 if (dp[j] < dp[j-a[i].s] + a[i].v) 41 { 42 dp[j] = dp[j-a[i].s] + a[i].v; 43 44 g[j].clear(); 45 46 for (int k = 0;k < g[j-a[i].s].size();k++) 47 g[j].push_back(g[j-a[i].s][k]); 48 49 g[j].push_back(a[i].id); 50 } 51 } 52 } 53 54 int ans = 0,id = 0; 55 56 for (int i = 1;i <= a[n].e;i++) 57 { 58 if (dp[i] > ans) 59 { 60 ans = dp[i]; 61 id = i; 62 } 63 } 64 65 printf("%d\n",ans); 66 printf("%d\n",g[id].size()); 67 68 for (int i = 0;i < g[id].size();i++) 69 { 70 if (!i) printf("%d",g[id][i]); 71 else printf(" %d",g[id][i]); 72 } 73 74 return 0; 75 }
康复训练中~欢迎交流!