http://codeforces.com/contest/864/problem/E
题意:题目有点长,主要是讲了一连串的故事。。。。(01背包问题+路径输出)了解了是01背包之后,就能很好的理解题意了。
大致说一下题意,就是给你三个数组 ti, di, pi (1 ≤ ti ≤ 20, 1 ≤ di ≤ 2 000, 1 ≤ pi ≤ 20)
三个数组的意思分别表示为 第i个文件:保存所需的时间为ti,到了时间di则会毁坏,和可得的价值pi。
输出第一行为最后能得到的最大价值是多少;
第二行为选择保存了多少个文件;
第三行为文件的id。
题解:我们首先要对d进行小者优先顺序排序,(之后便是01背包问题了,可以使用一维数组也可以使用二维数组,我这里使用的是一维数组)dp[j]表示j时刻内能保存的文件的
最大价值和,在进行dp的过程中使用pos[id][j]数组对其进行标记,标记a[i].id这个文件是否被选取了。
之后的就。。看代码好理解点吧
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=2100; 4 int n; 5 int pos[110][maxn];///pos[i][j]标记id为i并且总共花费了j时间的这个点 6 int dp[maxn]; 7 struct node 8 { 9 int t,d,p,id; 10 bool operator <(const node &x) const 11 { 12 return d<x.d; 13 } 14 }a[110]; 15 int main() 16 { 17 scanf("%d",&n); 18 for(int i=1;i<=n;i++) 19 { 20 scanf("%d%d%d",&a[i].t,&a[i].d,&a[i].p); 21 a[i].id=i; 22 } 23 memset(pos,0,sizeof(pos)); 24 memset(dp,0,sizeof(dp)); 25 sort(a+1,a+1+n); 26 for(int i=1;i<=n;i++) 27 { 28 if(a[i].t>a[i].d) 29 continue; 30 for(int j=a[i].d-1;j>=a[i].t;j--) 31 { 32 if(dp[j]<dp[j-a[i].t]+a[i].p) 33 { 34 dp[j]=dp[j-a[i].t]+a[i].p; 35 pos[a[i].id][j]=a[i].id; 36 } 37 } 38 } 39 int val=0; 40 int num=0; 41 for(int j=0;j<=a[n].d;j++) 42 { 43 if(dp[j]>val) 44 { 45 val=dp[j]; 46 num=j; 47 } 48 } 49 printf("%d\n",val); 50 stack<int>s; 51 for(int i=n;i>0;i--) 52 { 53 if(pos[a[i].id][num]) 54 { 55 s.push(a[i].id); 56 num=num-a[i].t; 57 } 58 } 59 printf("%d\n",s.size()); 60 while(s.size()) 61 { 62 printf("%d ",s.top()); 63 s.pop(); 64 } 65 return 0; 66 }
以前讲过路径保存,没太过于注意这方面,刚好遇到就记一下它。