POJ 1482 It's not a Bug, It's a Feature! 状压+spfa

http://poj.org/problem?id=1482

题意:先黑了一发程序猿,说软件总是有漏洞,然后打补丁拆了东墙补西墙。现在软件有不超过20个漏洞,有不超过100个补丁,每个补丁有运用条件(某些漏洞不能存在,某些漏洞必须存在)和作用效果(补漏洞,产生新漏洞),已经安装时间,开始有所有漏洞,问是否有一种安装补丁的顺序能填补所有漏洞,并求最短的时间。

分析:因为只有20个漏洞,所以可以状压,大概100万的级别,每位为0表示没有这个漏洞,为1表示有这个漏洞。记f[i]表示达到状态i所需最短时间,初始状态即 f[(1<<n)-1] = 0,目标状态为f[0]。

开始用dfs把序列里的0全部枚举成+-,然后连边spfa。。最后要么mle,要么wa,要么re。。直接连边,边数太大了。。实际上很多状态和边是没有必要的。具体怎么转移还是看程序吧。。

注意位运算优先级十分低,连比较运算符都低,所以尽量多加括号。

记忆化搜索貌似写不好会爆栈,然后网上还有的用bfs+堆过的。。仔细观察了一下貌似是spfa的“堆优化”,估计和上次slf优化一样,会被某些数据卡。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 const int maxq = (1<<20) + 10;
 7 int q[(1<<20)+15];
 8 int n, m, maxn, oo, w[110];
 9 int f[(1<<20)+10], ha[(1<<20)+10];
10 int cas = 0;
11 char s1[30], s2[30];
12 bool in[(1<<20)+10];
13 int pre[110][2], fixed[110][2];
14 void cook_the_raw(int i)
15 {
16     pre[i][0] = pre[i][1] = fixed[i][1] = 0;
17     fixed[i][0] = maxn;
18     for (int j = 0; j < n; j++){
19         if (s1[j] == '+') pre[i][1] += 1 << j;        //pre[i][1]某位为1表示patch[i]apply条件要求该漏洞
20         else if (s1[j] == '-') pre[i][0] += 1 << j;     //pre[i][0]某位为1表示patch[i]apply条件要求无该漏洞
21         if (s2[j] == '+') fixed[i][1] += 1 << j;       //fixed[i][1]某位为1表示apply后得到该漏洞
22         else if (s2[j] == '-') fixed[i][0] -= 1 << j;    //fixed[i][0]某位为0表示apply后修复该漏洞
23     }
24 }
25 void init()
26 {
27     cas ++;
28     maxn = (1 << n) - 1;
29     f[maxn] = 0; ha[maxn] = cas;
30     for (int i = 0; i < m; i++){
31         scanf("%d %s %s", &w[i], s1, s2);
32         cook_the_raw(i);
33     }
34 }
35 void spfa()
36 {
37     int head, tail;
38     head = tail = 0;
39     q[tail++] = maxn;
40     in[maxn] = true;
41     while (head != tail)
42     {
43         int u = q[head++];
44         if (head == maxq) head = 0;
45         for (int i = 0; i < m; i++){
46             if (((u & pre[i][1]) == pre[i][1]) && ((u & pre[i][0]) == 0)){  //满足patch[i]apply条件
47                 int v = (u | fixed[i][1]) & fixed[i][0];             //转移到的状态
48                 if (ha[v] != cas || f[v] > f[u] + w[i]){
49                     f[v] = f[u] + w[i]; ha[v] = cas;
50                     if  (!in[v]){
51                         q[tail++] = v;
52                         if (tail == maxq) tail = 0;
53                         in[v] = true;
54                     }
55                 }
56             }
57         }
58         in[u] = false;
59     }
60 }
61 void print()
62 {
63     printf("Product %d\n", cas); 
64     if (ha[0] != cas) printf("Bugs cannot be fixed.\n\n");
65     else printf("Fastest sequence takes %d seconds.\n\n", f[0]);
66 }
67 int main()
68 {
69     memset(in, false, sizeof(in));
70     memset(ha, 0, sizeof(ha));
71     while(scanf("%d %d", &n, &m) && n+m)
72     {
73         init();
74         spfa();
75         print();
76     }
77     return 0;
78 }

 

posted @ 2014-08-11 16:51  james47  阅读(259)  评论(0编辑  收藏  举报