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\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 }
代码君

 

你可能感兴趣的:(home)