非常好的状态DP 典型的状态DP
// +/- > (<<) > == > |/& #include <stdio.h> #include <stack> using std::stack; const int INF = 0x3f3f3f3f ; struct node { char name[105]; int deadline, time; }course[17]; struct DP { int point, time, pos, past; }dp[1<<17]; stack<int> s; int main() { int cas, i, j, x, n; scanf("%d", &cas); while( cas-- ) { scanf("%d", &n); memset(dp, 0, sizeof(dp)); for(i=1; i<=n; i++) scanf("%s %d %d", course[i].name, &course[i].deadline, &course[i].time); int valid = (1<<n)-1 ; for(i=1; i<=valid; i++) { dp[i].point = INF ; for(j=n-1; j>=0; j--) // 控制字典序输出 if((i | (1<<j)) == i) { //time -> cut -> point //past、pos拿来追踪的 int pre = i - (1<<j) ; int cut = dp[pre].time + course[j+1].time - course[j+1].deadline; if( cut < 0 ) cut = 0; if( dp[i].point > cut + dp[pre].point ) { dp[i].point = cut + dp[pre].point; dp[i].time = dp[pre].time + course[j+1].time; dp[i].pos = j+1; dp[i].past = pre; } } } printf("%d\n", dp[valid].point); x = valid; while(x!=0) { s.push(dp[x].pos); x = dp[x].past; } while(!s.empty()) { printf("%s\n", course[s.top()].name); s.pop(); } } return 0; }