Codeforces #436 Div2 E

#436 Div2 E

题意

某人的房子着火了,现在有 \(n\) 件物品待抢救,每件物品有抢救需要的时间和自身的价值,以及过多长时间物品会损坏。问最多一共可以抢救价值多少的物品?

分析

看数据就知道是 \(DP\) 了。
考虑怎么去 \(DP\) ,因为给出物品是无序的,需要我们自己去决定顺序,显然不能直接去枚举 \(n\) 个物品,注意到时间是天然有序的,很容易想到去枚举时间,\(dp[i]\) 表示到时间 \(i\) 为止的物品价值总和。因为每种物品只能选择一次,所以在枚举的过程中有 01 背包的思想。

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, dp[2002];
struct P {
    int i, t, p;
};
vector<P> G[2002];
vector<int> V[2002];
int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    cin >> n;
    for(int i = 0; i < n; i++) {
        int t, d, p;
        cin >> t >> d >> p;
        G[d].push_back(P{i + 1, t, p});
    }
    for(int i = 2; i < 2002; i++) {
        if(G[i].size() > 0) {
            for(auto v : G[i]) {
                for(int j = i; j > v.t; j--) {
                    int tmp = dp[j - v.t] + v.p;
                    if(dp[j] < tmp) {
                        dp[j] = tmp;
                        V[j] = V[j - v.t];
                        V[j].push_back(v.i);
                    }
                }
            }
        }
        if(dp[i] < dp[i - 1]) {
            dp[i] = dp[i - 1];
            V[i] = V[i - 1];
        }
    }
    cout << dp[2001] << endl;
    cout << V[2001].size() << endl;
    for(auto i : V[2001]) cout << i << " ";
    cout << endl;
    return 0;
}
posted @ 2017-09-26 22:01  ftae  阅读(129)  评论(0编辑  收藏  举报