In the second test case, both Computer->English->Math and Computer->Math->English leads to reduce 3 points, but the word "English" appears earlier than the word "Math", so we choose the first order. That is so-called alphabet order.
状态压缩DP,我们可以使用一个二进制的数来表示做作业的状态,1表示做了,0表示没做
dp[i]表示状态i损失的分数,再做一个作业x可到另一状态dp[j],则要有i&x==0,若要有dp[a],dp[b]均可以到达dp[j],那么选择损失分数最小的,若分数相同,按题意的字典序,即选择a和b中较小的一个,因为题目的课程是按字典序给出的。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; struct node { int time, pre, cost; }dp[1<<15]; struct Node { int deadline, work; char subject[200]; }a[15]; void fun(int t) { int i, num=0; i = dp[t].pre^t; i >>= 1; while (i) { num++; i >>= 1; } if (dp[t].pre) fun(dp[t].pre); printf("%s\n", a[num].subject); } int main() { int t, n, i, flag[1 << 15], j, k, cur, temp; cin >> t; while (t--) { cin >> n; for (i = 0;i < n;i++) cin >> a[i].subject >> a[i].deadline >> a[i].work; int t1 = (1 << n) - 1; memset(flag, 0, sizeof(flag)); dp[0].time = 0, dp[0].pre = -1, dp[0].cost = 0, flag[0] = 1; for (i = 0;i < t1;i++) { for (j = 0;j < n;j++) { cur = 1 << j; if ((cur&i) == 0) { k = cur | i; dp[k].time = dp[i].time + a[j].work; temp = dp[k].time - a[j].deadline; if (temp < 0) temp = 0; temp += dp[i].cost; if (flag[k]) { if (temp < dp[k].cost) { dp[k].cost = temp; dp[k].pre = i; } else if (temp == dp[k].cost) { if (dp[k].pre>i) dp[k].pre = i; } } else { flag[k] = 1, dp[k].cost = temp, dp[k].pre = i; } } } } cout << dp[t1].cost << endl; fun(t1); } return 0; }