CodeForces - 864E Fire(dp)

思路

01背包dp,需要注意的是物品过了d[i]秒后就会焚毁,这使得背包的选取顺序影响了dp的更新。这是为什么呢?考虑我们背包的过程,我们为了避免选取顺序的影响强制给了背包一个顺序,而由于我们先放了a大小的,后面b大小只要空间足够的肯定能放,反之亦然。也就是说背包的选取顺序对dp的更新没有影响。但是这里因为物品焚毁,如果我们先放了a大小的结果发现b已经焚毁了就没法更新状态了,但实际上我们能把先焚毁的b放进去来更新状态,所以我们将d排序后再跑背包dp,这样保证了先焚毁的能更新后焚毁的物品的状态。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <bits/stdc++.h>
#define ll long long
#define INF 0x7fffffff
#define ms(a,val) memset((a),(val),(sizeof(a)))

using namespace std;

struct node{
int t,d,p,id;
}pack[105];
bool cmp(node n1,node n2){
return n1.d<n2.d;
}

int dp[2005];
vector<int> v[2005];

int main() {
int n;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>pack[i].t>>pack[i].d>>pack[i].p;
pack[i].id=i;
}
ms(dp,0);
//sort(pack,pack+n,cmp);
for(int i=0;i<n;i++){
for(int j=pack[i].d-1;j>=pack[i].t;j--){
if(dp[j-pack[i].t]+pack[i].p>dp[j]){
dp[j]=dp[j-pack[i].t]+pack[i].p;
v[j]=v[j-pack[i].t];
v[j].push_back(pack[i].id);
}
}
}
int maxs=-1,pos;
for(int i=0;i<=2000;i++)if(dp[i]>maxs)maxs=dp[i],pos=i;
cout<<maxs<<endl;
cout<<v[pos].size()<<endl;
for(vector<int>::iterator it=v[pos].begin();it!=v[pos].end();it++){
if(it!=v[pos].begin())cout<<" ";
cout<<*it+1;
}
cout<<endl;
for(int i=0;i<2005;i++)v[i].clear();
}
return 0;
}