http://acm.hdu.edu.cn/showproblem.php?pid=1074
每个任务有一个截止日期和完成时间,超过截止日期一天扣一分,问完成全部任务最少扣几分,并输出路径
最多15个任务,状态压缩一下进行dp,输出路径的话要记录每种状态的前驱,存起来逆序输出
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cstring> #include <map> using namespace std; const int INF = 0xfffffff; struct fuck{ int w, pre; }dp[1<<15]; struct node{ char name[105]; int D, C; }p[16]; int cal(int x){ int res = 0, cnt = 0; while(x){ if(x & 1){ res += p[cnt].C; } cnt++; x >>= 1; } return res; } int cnt(int x){ int res = 0; while(x){ if(x & 1){ res++; } x >>= 1; } return res; } int cal1(int x, int y){ int res = 0; while(1){ if((x&1) != (y&1)){ return res; } res++; x >>= 1; y >>= 1; } } int ans[25], ct; int main(){ int T; scanf("%d", &T); while(T--){ int n; scanf("%d", &n); for(int i = 0; i < (1<<n); i++) dp[i].w = INF; int xx = 0; while(1){ dp[(1<<xx)].pre = 0; xx++; if(xx == n) break; } for(int i = 0;i < n; i++){ scanf("%s %d %d", p[i].name, &p[i].D, &p[i].C); if(p[i].C > p[i].D) dp[1<<i].w = p[i].C - p[i].D; else dp[1<<i].w = 0; } map <int, int> mp; for(int i = 0; i < (1<<n); i++){ for(int j = 0; j < n; j++){ if(i&(1<<j)){ if(cal(i) > p[j].D){ if(dp[i].w > dp[i^(1<<j)].w + cal(i) - p[j].D){ dp[i].w = dp[i^(1<<j)].w + cal(i) - p[j].D; dp[i].pre = i^(1<<j); mp[i] = i^(1<<j); } else if(dp[i].w == dp[i^(1<<j)].w + cal(i) - p[j].D && dp[i].pre > (i^(1<<j))){ dp[i].pre = i^(1<<j); mp[i] = i^(1<<j); } //dp[i] = min(dp[i], dp[i^(1<<j)] + cal(i) - p[j].D); } else{ if(dp[i].w > dp[i^(1<<j)].w){ dp[i].w = dp[i^(1<<j)].w; dp[i].pre = i^(1<<j); mp[i] = i^(1<<j); } else if(dp[i].w == dp[i^(1<<j)].w && dp[i].pre > (i^(1<<j))){ dp[i].pre = i^(1<<j); mp[i] = i^(1<<j); } //dp[i] = min(dp[i], dp[i^(1<<j)]); } } } } printf("%d\n", dp[(1<<n)-1]); int now = (1<<n) - 1; ct = 0; while(now){ ans[ct++] = cal1(now, mp[now]); now = mp[now]; } for(int i = n - 1; i >= 0; i--){ printf("%s\n", p[ans[i]].name); } } return 0; }