题解 :
这个题不难想到动态规划,但是想到动态规划并不能解决这个问题,
dp[i,j,k0 表示前 i 个选了 j 个 用了 k 时间 所拯救物品的最大值,这样的话我们 就可以dp了
但是这个题和0\1背包的不同之处在于这个题选择的先后次序影响了这个题的答案 什么叫先后次序影响答案呢 ?
对于 0 1 背包而言,先选 a 后选 b 和 先选 b 后选 a 没有什么区别,但是这个题就不一样了 先选 a 和 先选 b 会对结果造成影响。 比如说 我的
a.t = 1, a.d = 3,a.p = 5;
b.t = 3, b.d = 5,b.p = 6;
对于这种数据而言 我如果先选择救 a 那么我最后可以把 a,b全部救出来 ,但是我要是先选择 b 那就只能把 b 弄出来a就只能gg了
对于这种问题 我们就需要选择一种最佳的排序方式进行dp ,
不难发现按照 d 从小到大正符合这种条件,这样进行dp就可以了
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 105;
struct node {
int id,t,d,p;
}a[maxn];
int dp[maxn][maxn][2005] = {0};
int now[maxn][maxn][2005] = {0};
int res[maxn] = {0};
bool vis[maxn] = {0};
bool cmp (const node a,const node b) {
return a.d < b.d;
}
int main () {
ios_base :: sync_with_stdio(false);
int n;
cin >> n;
for (int i = 1;i <= n; ++ i) {
a[i].id = i;
cin >> a[i].t >> a[i].d >> a[i].p;
}
sort (a + 1,a + n + 1,cmp);
int ans = 0;
int cnt = 0;
int first = 0;
int second = 0;
int time = 0;
for (int i = 1;i <= n; ++ i) {
for (int j = 1;j <= i; ++ j) {
for (int k = 1;k < 2001; ++ k) {
dp[i][j][k] = dp[i][j - 1][k];
now[i][j][k] = now[i][j - 1][k];
if (j != i) {
if (dp[i-1][j][k] > dp[i][j][k]) {
dp[i][j][k] = dp[i - 1][j][k];
now[i][j][k] = now[i - 1][j][k];
}
}
if (k < a[i].d && k - a[i].t >= 0) {
if (dp[i - 1][j - 1][k - a[i].t] + a[i].p > dp[i][j][k]) {
dp[i][j][k] = dp[i - 1][j - 1][k - a[i].t] + a[i].p;
now[i][j][k] = i;
}
}
if (ans < dp[i][j][k]) {
ans = dp[i][j][k];
cnt = j;
first = i;
time = k;
}
}
}
}
second = cnt;
int u = now[first][second][time];
int temp = cnt;
cout << ans << endl << cnt << endl;
vis[0] = 1;
for (int i = 0;i < temp; ++ i) {
cout << res[i] << ' ';
}
cout << endl;
return 0;
}
/*
9
13 18 14
8 59 20
9 51 2
18 32 15
1 70 18
14 81 14
10 88 16
18 52 3
1 50 6
106
8
1 4 9 8 2 5 6 7
*/