Codeforces Round #436 (Div. 2) E. Fire(DP+记录路径)

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 }

以前讲过路径保存,没太过于注意这方面,刚好遇到就记一下它。

转载于:https://www.cnblogs.com/Y-Meng/p/8590390.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值