首页 > 技术文章 > UVa 658 (Dijkstra) It's not a Bug, it's a Feature!

AOQNRMGYXLMV 2015-01-28 18:31 原文

题意:

有n个BUG和m个补丁,每个补丁用一个串表示打补丁前的状态要满足的要求,第二个串表示打完后对补丁的影响,还有打补丁所需要的时间。

求修复所有BUG的最短时间。

分析:

可以用n个二进制位表示这n个BUG的当前状态。最开始时所有BUG都存在,所以状态为n个1.目标状态是0

当打上一个补丁时,状态就会发生转移。因为有可能一个补丁要打多次,所以这个图不是DAG。

可以用Dijkstra算法,求起始状态到终态的最短路。代码中用了优先队列优化。

 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 const int maxn = 20;
 7 const int maxm = 100 + 10;
 8 const int INF = 1000000000;
 9 
10 int n, m, t[maxm], dist[1<<maxn], mark[1<<maxn];
11 char before[maxm][maxn + 5], after[maxm][maxn + 5];
12 
13 struct Node
14 {
15     int bugs, dist;
16     bool operator < (const Node& rhs) const
17     {//优先级大的排在前面,老是弄错=_=||
18         return dist > rhs.dist;
19     }
20 };
21 
22 int solve()
23 {
24     for(int i = 0; i < (1<<n); ++i) { dist[i] = INF; mark[i] = 0; }
25     priority_queue<Node> q;
26 
27     Node start;
28     start.dist = 0;
29     start.bugs = (1<<n) - 1;
30 
31     dist[start.bugs] = 0;
32     q.push(start);
33 
34     while(!q.empty())
35     {
36         Node u = q.top(); q.pop();
37         if(u.bugs == 0) return u.dist;
38         if(mark[u.bugs]) continue;
39         mark[u.bugs] = 1;
40         for(int i = 0; i < m; ++i)
41         {
42             bool flag = true;
43             for(int j = 0; j < n; ++j)
44             {//是否满足打补丁的条件
45                 if(before[i][j] == '+' && !(u.bugs & (1<<j))) { flag = false; break; }
46                 if(before[i][j] == '-' &&   u.bugs & (1<<j) ) { flag = false; break; }
47             }
48             if(!flag) continue;
49 
50             Node u2;
51             u2.dist = u.dist + t[i];
52             u2.bugs = u.bugs;
53             for(int j = 0; j < n; ++j)
54             {//打完补丁以后的状态
55                 if(after[i][j] == '+') u2.bugs |= (1 << j);
56                 if(after[i][j] == '-') u2.bugs &= ~(1 << j);
57             }
58             int &D = dist[u2.bugs];
59             if(u2.dist < D)
60             {
61                 D = u2.dist;
62                 q.push(u2);
63             }
64         }
65     }
66 
67     return -1;
68 }
69 
70 int main()
71 {
72     //freopen("in.txt", "r", stdin);
73 
74     int kase = 0;
75     while(scanf("%d%d", &n, &m) == 2 && n && m)
76     {
77         for(int i = 0; i < m; ++i) scanf("%d%s%s", &t[i], before[i], after[i]);
78         int ans = solve();
79         printf("Product %d\n", ++kase);
80         if(ans < 0) puts("Bugs cannot be fixed.\n");
81         else printf("Fastest sequence takes %d seconds.\n\n", ans);
82     }
83 
84     return 0;
85 }
代码君

 

推荐阅读