时间:2016-03-28 18:46:36 星期一
题目编号:[2016-03-28][HDU][1074][Doing Homework]
题目大意:给定n门科作业的期限时间和完成耗时,每科每超过一天就扣一份,求最少扣分数
分析:n只有15,二进制枚举,状态压缩,枚举每种科目完成的状态,更新下一个状态,求最小值
#include <cstring>#include <cstdio>using namespace std;const int maxstu = 1 << 16;struct Cource{ char name[20]; int d,c;}a[16];struct mstatus{ int pre,cost,reduced,id; mstatus(int a = 0,int b = 0,int c = 0,int d = 0):cost(a),reduced(b),pre(c),id(d){};}dp[maxstu];int vis[maxstu];void print(int cur){ if(dp[cur].pre == 0){ printf("%s\n",a[ dp[cur].id ].name); return ; } print(dp[cur].pre); printf("%s\n",a[ dp[cur].id ].name);}int main(){ int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); for(int i = 0;i < n;++i){ scanf("%s%d%d",a[i].name,&a[i].d,&a[i].c); } memset(vis,0,sizeof(vis)); dp[0] = mstatus(0,0,0,0); for(int i = 0;i < (1 << n) - 1;++i){ for(int j = 0;j < n;++j){ int cur = 1 << j; if((cur & i) == 0){ int curcost = dp[i].cost + a[j].c; int curreduced = dp[i].reduced + (curcost <= a[j].d?0:curcost - a[j].d); int nxtstatus = cur | i; if(vis[nxtstatus]){ if(curreduced < dp[nxtstatus].reduced){ dp[nxtstatus] = mstatus(curcost,curreduced,i,j); } }else { vis[nxtstatus] = 1; dp[nxtstatus] = mstatus(curcost,curreduced,i,j); } } } } int ans = dp[(1 << n) - 1].reduced; printf("%d\n",ans); print((1 << n) - 1); } return 0;}