大意:
给出n((n<=15))个作业的用时和deadline,如果有作业超过deadline,那么每超过1天就要扣1分(超过多个作业也是1分),问扣分最少的方案,按字典序最小输出(题目保证输入按照字典序递增)
思路:
状压dp,枚举能转移过来的每个状态,更新dp数组即可
#include <bits/stdc++.h>
using namespace std;
const int N = 15 + 5;
typedef long long LL;
int T, n, d[N], t[N], dp[1 << N], l[1 << N], pre[1 << N], res[N], cnt,
step[1 << N];
string name[N];
int main() {
cin >> T;
while (T--) {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> name[i] >> d[i] >> t[i];
}
memset(dp, 0x3f, sizeof dp);
memset(l, 0, sizeof l);
dp[0] = 0;
for (int i = 0; i < (1 << n); i++) {
for (int j = 0; j < n; j++) {
if ((1 << j) & i) {
int prestate = i - (1 << j);
int temp = max(0, l[prestate] + t[j] - d[j]);
if (dp[prestate] + temp <= dp[i]) {
dp[i] = dp[prestate] + temp;
l[i] = l[prestate] + t[j];
pre[i] = prestate;
step[i] = j;
}
}
}
}
cnt = 0;
int state = ( 1 << n ) - 1;
cout << dp[state] << endl;
while (state != 0) {
res[cnt++] = step[state];
state = pre[state];
}
for (int i = cnt - 1; i >= 0; i--) {
cout << name[res[i]] << endl;
}
}
return 0;
}