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 }
POJ 1482 It's not a Bug, It's a Feature! 状压+spfa
时间: 2024-11-23 04:25:42