小 K 有 N 项工作等待完成,第 i 项工作需要花 ti 单位时间,必须在 di 时刻或之前完成,报酬为 pi。假设小 K 工作时刻从 0 开始,且同一时刻只能做一项工作、工作一旦开始则不可中断或切换至其他工作,请你帮小 K 规划一下如何选择合适的工作,使小 K 可以获得最多的报酬。
输入格式:
输入第一行是一个正整数 T (≤5),表示数据的组数。
接下来有 T 组数据,每组数据第一行是一个正整数 N (≤5000),表示待完成工作的数量。接下来的 N 行,每行三个非负整数 ti、di、pi (均 ≤5000;1≤i≤N),表示第 i 项工作需要花费的时间、截止时间以及报酬。
输出格式:
对于每组数据,输出小 K 能获得最多的报酬是多少。
输入样例:
3
5
1 2 50
3 3 100
1 5 1
3 2 5000
4 5 30
5
1 2 50
3 3 20
1 5 1
3 2 5000
4 5 30
5
1 2 50
3 3 100
1 5 1
3 2 5000
5 5 800
输出样例:
101
80
800
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
#define int long long //可能会超时
#define PII pair<int,int>
const int INF = 0x3f3f3f3f, mod = 998244353;
int T, n;
const int N = 5005;
int dp[N];
struct node {
int t, d, p;
}temp[N];
bool cmp(node a, node b) {
return a.d < b.d;
}
signed main()
{
ios::sync_with_stdio, cin.tie(0), cout.tie(0);
cin >> T;
while (T--) {
memset(dp, 0, sizeof dp);
cin >> n;
for (int i = 1;i <= n;i++) cin >> temp[i].t >> temp[i].d >> temp[i].p;
sort(temp + 1, temp + n + 1, cmp);
for (int i = 1;i <= n;i++) {
for (int j = temp[i].d;j >= temp[i].t;j--) {
dp[j] = max(dp[j], dp[j - temp[i].t] + temp[i].p);
}
}
int ans = -1;
for (int i = 0;i < N;i++) ans = max(ans, dp[i]);
cout << ans << endl;
}
return 0;
}
赛时没看出来是01背包,只写了模拟得了16分,结束后写01背包也只得了20分,后来发现只需要按截止时间排序即可 。。。另外要注意最后要一起取最大值,因为最大报酬不一定在截止时间取得。