题意:给定n个任务,每个任务有deadline和完成用时,若未能在deadline之前完成则须扣分,扣的分数等于延迟的天数,求完成所有任务扣分最少的方案
思路:对于完成的特定任务,其用时是固定不变的,但扣的分数取决于完成任务的顺序,故将当前完成了哪几项任务压缩到一个状态i里,取状态k为未完成当前任务j的状态,则k=i-(1<<j),保存下完成当前所有任务总用时,用DP枚举状态求每个状态的最小扣分即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = (1<<15)+10;
const int inf = 0x3f3f3f3f;
int T, n, c[maxn], d[maxn], dp[maxn], pre[maxn], t[maxn];
string S[maxn];
void output(int x)
{
if (!x)
return;
output(x-(1<<pre[x]));
printf("%s\n", S[pre[x]].c_str());
}
int main()
{
cin >> T;
for (int k = 0; k < T; k++) {
cin >> n;
int bit = 1<<n;
for (int j = 0; j < n; j++) {
cin >> S[j] >> d[j] >> c[j];
}
for (int i = 1; i < bit; i++) {
dp[i] = inf;
for (int j = n-1; j >= 0; j--) {
int temp = 1<<j;
if (!(i&temp)) continue;
int score = t[i-temp] + c[j] - d[j];
if (score < 0) score = 0;
if (dp[i] > dp[i-temp] + score) {
dp[i] = dp[i-temp] + score;
pre[i] = j;
t[i] = t[i-temp] + c[j];
}
}
}
printf("%d\n", dp[bit-1]);
output(bit-1);
}
return 0;
}