CF864E 题解
思路
显然是个 01 背包问题,背包容量 ,每个物品可以的拯救结束时间是 ,然后 ( 表示拯救第 个物品用了至多 个时间能获得的最大价值)可以从 转移过来。然后这题要输出方案,所以我们可以设一个 数组表示 是从 成功转移过来的,最后递归输出。如果 说明没有拯救这个物品,不用输出,直接递归。
注意事项
必须对 从小到大排序,因为肯定是用结束时间小的去更新结束时间大的物品,具体解释详见这里。
代码
# include <bits/stdc++.h>
using namespace std;
struct node {
int t, d, p, id;
bool operator < (const node& x) const {
return d < x.d;
}
} a[105];
int n, dp[105][2005], m, maxi, lst[105][2005];
vector <int> ans;
inline void dfs (int step, int x) {
if (! step)
return ;
dfs (step - 1, lst[step][x]);
if (lst[step][x] < x)
ans.emplace_back (a[step].id);
return ;
}
int main () {
ios::sync_with_stdio (0);
cin.tie (0);
cout.tie (0);
cin >> n;
for (int i = 1; i <= n; ++ i) {
cin >> a[i].t >> a[i].d >> a[i].p;
a[i].id = i;
m = max (m, a[i].d);
}
sort (a + 1, a + n + 1);
for (int i = 1; i <= n; ++ i) {
for (int j = 1; j < m; ++ j)
dp[i][j] = dp[i - 1][j], lst[i][j] = j;
for (int j = a[i].t; j < a[i].d; ++ j)
if (dp[i - 1][j - a[i].t] + a[i].p > dp[i][j])
dp[i][j] = dp[i - 1][lst[i][j] = j - a[i].t] + a[i].p;
}
for (int i = 1; i < m; ++ i)
if (dp[n][i] > dp[n][maxi])
maxi = i;
dfs (n, maxi);
cout << dp[n][maxi] << '\n' << ans.size () << '\n';
for (int i : ans)
cout << i << ' ';
return 0;
}

浙公网安备 33010602011771号