1. 程式人生 > >UVa 658 - It's not a Bug, it's a Feature!(Dijkstra + 隱式圖搜索)

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

index else bug class string 最短 enc 字符串表 字符串

鏈接:

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 }

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