hdu 1074 Doing Homework(狀壓DP)
阿新 • • 發佈:2018-11-08
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <queue> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; const int maxn = (1<<15)+10; struct node { int deadline;//截止時間 int how_day;//花費的時間 char name[110]; } nxt[20]; int dp[maxn]; int time[maxn]; int print[maxn]; void output(int x) { //列印路徑 dfs if(!x) return; output( x - (1<<print[x]) ); printf("%s\n", nxt[print[x]].name);//字典序 } int main() { freopen("data.in", "r", stdin); int T, n; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 0; i < n; i++) scanf("%s %d %d", nxt[i].name, &nxt[i].deadline, &nxt[i].how_day); int total = 1<<n; memset(time, 0, sizeof(time)); memset(print, 0, sizeof(print)); memset(dp, 0, sizeof(dp)); //全排列問題,狀壓dp for(int i = 1; i < total; i++) { dp[i] = INF; for(int j = n-1; j >= 0; j--) { int temp = 1<<j; if(!(i & temp)) continue;//沒有寫j門課的作業則跳出迴圈 int score = time[i-temp] + nxt[j].how_day - nxt[j].deadline;//扣得分數 score = max(score,0);//扣得分數不可能是負的 if(dp[i] > dp[i-temp] + score) { //如果當前狀態可以更優則更新dp值,和time的值 dp[i] = dp[i-temp] + score; time[i] = time[i-temp] + nxt[j].how_day; print[i] = j;//修改路徑 } } } //所有課作業做完應該所有為都為1,就是1<<n-1 printf("%d\n", dp[total-1]);//輸出扣得分數 output(total - 1);//列印路徑 } return 0; }