HDU 1074 Doing Homework

第一次做这道题大概是半个月前了吧,状压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
", 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
", dp[All].reduced);
78         OutPut(All);
79     }
80     return 0;
81 }
代码君
原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/3930925.html