UVa 658 - It's not a Bug, it's a Feature!(Dijkstra + 隐式图搜索)

链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=599

 

题意:

补丁在修正bug时,有时也会引入新的bug。假定有n(n≤20)个潜在bug和m(m≤100)个补丁,
每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug。
第一个串表示打补丁之前的状态(“-”表示该bug必须不存在,“+”表示必须存在,0表示无所谓),
第二个串表示打补丁之后的状态(“-”表示不存在,“+”表示存在,0表示不变)。
每个补丁都有一个执行时间,你的任务是用最少的时间把一个所有bug都存在的软件通过打补丁的方式变得没有bug。
一个补丁可以打多次。

 

分析:

在任意时刻,每个bug可能存在也可能不存在,所以可以用一个n位二进制串表示当前软件的“状态”。
打完补丁之后,bug状态会发生改变,对应“状态转移”。
把状态看成结点,状态转移看成边,转化成图论中的最短路径问题,然后使用Dijkstra算法求解。
不过这道题和普通的最短路径问题不一样:结点很多,多达2^n个,
而且很多状态根本遇不到(即不管怎么打补丁,也不可能打成那个状态),所以没有必要先把图储存好。
用隐式图搜索即可:当需要得到某个结点u出发的所有边时,直接枚举所有m个补丁,看看是否能打得上。

 

代码:

 1 import java.io.*;
 2 import java.util.*;
 3 import static java.util.Arrays.*;
 4 
 5 public class Main {
 6     Scanner cin = new Scanner(new BufferedInputStream(System.in));
 7     final int INF = 0x3f3f3f3f;
 8     final int UPN = 20;
 9     final int UPM = 100;
10     int n, m, sec[] = new int[UPM], d[] = new int[1<<UPN];
11     char before[][] = new char[UPM][UPN], after[][] = new char[UPM][UPN];
12     boolean done[] = new boolean[1<<UPN];
13     
14     class Node implements Comparable<Node> {
15         int s, dist;
16         
17         Node(int s, int dist) {
18             this.s = s;
19             this.dist = dist;
20         }
21         
22         @Override
23         public int compareTo(Node that) {
24             return dist - that.dist;
25         }
26     }
27     
28     int dijkstra() {
29         fill(d, INF);
30         fill(done, false);
31         int ori = (1<<n) - 1;
32         PriorityQueue<Node> Q = new PriorityQueue<Node>();
33         d[ori] = 0;
34         Q.add(new Node(ori, 0));
35         while(Q.size() > 0) {
36             Node cur = Q.poll();
37             if(cur.s == 0) return cur.dist;
38             if(done[cur.s]) continue;
39             done[cur.s] = true;
40             for(int t = 0; t < m; t++) {
41                 boolean patchable = true;
42                 for(int i = 0; i < n; i++) {
43                     if(before[t][i] == '+' && (cur.s&(1<<i)) == 0) { patchable = false; break; }
44                     else if(before[t][i] == '-' && (cur.s&(1<<i)) > 0) { patchable = false; break; }
45                 }
46                 if(!patchable) continue;
47                 
48                 Node temp = new Node(cur.s, cur.dist + sec[t]);
49                 for(int i = 0; i < n; i++) {
50                     if(after[t][i] == '+') temp.s |= (1<<i);
51                     else if(after[t][i] == '-') temp.s &= ~(1<<i);
52                 }
53                 if(d[temp.s] > temp.dist) {
54                     d[temp.s] = temp.dist;
55                     Q.add(temp);
56                 }
57             }
58         }
59         return -1;
60     }
61     
62     void MAIN() {
63         for(int cases = 1; ; cases++) {
64             n = cin.nextInt();
65             m = cin.nextInt();
66             if(n + m == 0) break;
67             for(int i = 0; i < m; i++) {
68                 sec[i] = cin.nextInt();
69                 before[i] = cin.next().toCharArray();
70                 after[i] = cin.next().toCharArray();
71             }
72             int ans = dijkstra();
73             System.out.printf("Product %d\n", cases);
74             if(ans < 0) System.out.printf("Bugs cannot be fixed.\n\n");
75             else System.out.printf("Fastest sequence takes %d seconds.\n\n", ans);
76         }
77     }
78     
79     public static void main(String args[]) { new Main().MAIN(); }
80 }

 

posted @ 2018-08-24 22:51  Ctfes  阅读(238)  评论(0编辑  收藏  举报