hdu 1074 状态压缩

http://acm.hdu.edu.cn/showproblem.php?pid=1074

我们可以断定状态的终止态一定是n个数全部选完的情况,那么它的前一个状态是什么呢,一定是剔除任一门课程后的n种状态。

例如

dp[全选了]=min{(dp[除了math都做了]+math的超时天数),(dp[除了computer都做了]+computer的超时天数),(dp[除了english都做了]+english的超时天数)}那么接下来的dp状态依然如此。

好了,接下来,我们该如何去思考了,这个题目共有2^15种可能情况,对此我们通过位运算方法降低它的维度。

二进制的每一位代表一门课,它的组合可以完成展示出所有的状态。

最后我们应该去思考一个问题,顺序的问题,我们知道,第一次取得时候,一定只有一个课程,如果我们以

1 int bit = 1<<n;
2 for(int i = 1;i<bit;i++)

能否确保某一个状态的前一个都完全包含,你可以自己去检验,是完全满足的.

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int MAXN = (1<<15)+10;
 7 const int INF = 0x3f3f3f;
 8 struct node
 9 {
10     char str[105];
11     int d;//the deadtime
12     int c;//need spend time
13 };
14 node nd[20];
15 int dp[MAXN],pre[MAXN],t[MAXN];
16 void output(int x)
17 {
18     if(!x)
19         return ;
20     output(x-(1<<(pre[x]-1)));
21     printf("%s\n",nd[pre[x]].str);
22 }
23 int main()
24 {
25     int cas,n;
26     scanf("%d",&cas);
27     while(cas--)
28     {
29         memset(t,0,sizeof(t));
30         memset(pre,0,sizeof(pre));
31         //memset(dp,0,sizeof(dp));
32         scanf("%d",&n);
33         for(int i = 1;i<=n;i++)
34         {
35             scanf("%s%d%d",nd[i].str,&nd[i].d,&nd[i].c);
36         }
37        /* for(int i = 1;i<=n;i++)
38         {
39             printf("%s %d %d\n",nd[i].str,nd[i].d,nd[i].c);
40         }*/
41         int bit = 1<<n;
42         for(int i = 1;i<bit;i++)
43         {
44             dp[i] = INF;
45             for(int j = n;j>=1;j--)
46             {
47                 int temp = 1<<(j-1);
48                 if(!(temp&i))
49                     continue;
50                 else
51                 {
52                     int dist = (t[i-temp]+nd[j].c-nd[j].d);
53                     if(dist > 0)
54                     {
55                         if(dp[i]>(dp[i-temp]+dist))
56                         {
57                             t[i]=t[i-temp]+nd[j].c;
58                             dp[i]=dp[i-temp]+dist;
59                             pre[i] = j;
60                         }
61                     }
62                     else
63                     {
64                         if(dp[i]>dp[i-temp])
65                         {
66                             t[i]=t[i-temp]+nd[j].c;
67                             dp[i]=dp[i-temp];
68                             pre[i] =j;
69                         }
70                     }
71                 }
72             }
73         }
74         cout<<dp[bit-1]<<endl;
75         output(bit-1);
76     }
77     return 0;
78 }

 

posted @ 2016-03-26 22:06  fancy_boy  阅读(167)  评论(0编辑  收藏  举报