标签:style blog http color os io for ar art
第一次做这道题大概是半个月前了吧,状压DP一个很新鲜的名词
当时看题解怎么也看不懂,现在看懂了以后还是很简单的
所谓状态压缩就是用一个整数的二进制来表示一个状态,比如有三个作业
000表示一科作业也没做,001表示只做了第一科,111表示三科作业都做了
那么从状态0开始出发,遍历每一个状态,如果对于状态S有第i科作业没写那么计算该状态下做完第i科作业对应的扣分数,如果比别人状态下转移过来的扣分数要少,那么状态S就是下一个状态的前驱
用结构体里的pre来保存路径
最后输出科目的时候用递归输出,也是一种很常用的方法
1 //#define LOCAL 2 #include <cstdio> 3 #include <cstring> 4 5 const int maxn = (1 << 16); 6 struct Node 7 { 8 int used; 9 int pre; 10 int reduced; 11 }dp[maxn]; 12 13 struct Course 14 { 15 int deadline; 16 int cost; 17 char name[202]; 18 }course[16]; 19 20 bool vis[maxn]; 21 22 void OutPut(int S) 23 { 24 int t = S ^ dp[S].pre; 25 int i = -1; 26 while(t) 27 { 28 t >>= 1; 29 ++i; 30 } 31 if(dp[S].pre != 0) 32 OutPut(dp[S].pre); 33 printf("%s\n", course[i].name); 34 } 35 36 int main(void) 37 { 38 #ifdef LOCAL 39 freopen("1074in.txt", "r", stdin); 40 #endif 41 42 int T; 43 scanf("%d", &T); 44 while(T--) 45 { 46 int n; 47 scanf("%d", &n); 48 for(int i = 0; i < n; i++) 49 scanf("%s%d%d", course[i].name, &course[i].deadline, &course[i].cost); 50 memset(vis, false, sizeof(vis)); 51 vis[0] = true; 52 dp[0].used = 0, dp[0].pre = -1, dp[0].reduced = 0; 53 int All = (1 << n) - 1; 54 for(int S = 0; S < All; ++S) 55 for(int i = 0; i < n; ++i) 56 { 57 if((S & (1 << i)) == 0) 58 {//S状态下第i项作业还没做 59 Node temp; 60 int next = S | (1 << i); 61 temp.used = dp[S].used + course[i].cost; 62 temp.pre = S; 63 temp.reduced = temp.used - course[i].deadline; 64 if(temp.reduced < 0) temp.reduced = 0; 65 temp.reduced += dp[S].reduced; 66 67 if(vis[next] && temp.reduced < dp[next].reduced) 68 dp[next] = temp; 69 else if(!vis[next]) 70 { 71 vis[next] = true; 72 dp[next] = temp; 73 } 74 } 75 } 76 77 printf("%d\n", dp[All].reduced); 78 OutPut(All); 79 } 80 return 0; 81 }
标签:style blog http color os io for ar art
原文地址:http://www.cnblogs.com/AOQNRMGYXLMV/p/3930925.html