UVa 658 (Dijkstra) It's not a Bug, it's a Feature!

题意:

有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 }

代码君

UVa 658 (Dijkstra) It's not a Bug, it's a Feature!

时间: 2024-10-12 17:36:15

UVa 658 (Dijkstra) It's not a Bug, it's a Feature!的相关文章

【uva 658】It&#39;s not a Bug, it&#39;s a Feature!(图论--Dijkstra算法+二进制表示)

题意:有n个潜在的bug和m个补丁,每个补丁用长为n的字符串表示.首先输入bug数目以及补丁数目.然后就是对m 个补丁的描述,共有m行.每行首先是一个整数,表明打该补丁所需要的时间.然后是两个字符串,地一个字符串 是对软件的描述,只有软件处于该状态下才能打该补丁该字符串的每一个位置代表bug状态(-代表该位置没bug,+代 表该位置有bug,0表示该位置无论有没有bug都可打补丁).然后第二个字符串是对打上补丁后软件状态的描述 -代表该位置上的bug已经被修复,+表示该位置又引入了一个新的bug

UVA 658 It&#39;s not a Bug, it&#39;s a Feature! (单源最短路,dijkstra+优先队列,变形,经典)

题意:有n个bug,有m个补丁,每个补丁有一定的要求(比如某个bug必须存在,某个必须不存在,某些无所谓等等),打完出来后bug还可能变多了呢.但是打补丁是需要时间的,每个补丁耗时不同,那么问题来了:要打多久才能无bug?(同1补丁可重复打) 分析: n<=20,那么用位来表示bug的话有220=100万多一点.不用建图了,图实在太大了,用位图又不好玩.那么直接用隐式图搜索(在任意点,只要满足转移条件,任何状态都能转). 但是有没有可能每个状态都要搜1次啊?那可能是100万*100万啊,这样出题

UVa 658 - It&#39;s not a Bug, it&#39;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必须不存在,"+&

658 - It&#39;s not a Bug, it&#39;s a Feature! (Dijkstra算法)

今天第一次系统的学习了一下最短路算法,开始刷第十一章,第一次写Dijkstra算法,出现了很多喜闻乐见的错误..而且uva上样例很水,瓢虫也很水 ,坑了我好久. 首先是对于结点的处理,我们必须要维护一个二元组,一个表示结点一个表示当前结点最短路.   因为Dijkstra算法利用了优先队列来加速算法,所以需要定义小于运算符,一开始我直接将状态装进了优先队列,显然是不对的,因为优先队列的作用就是取出当前距离最短的结点. 其次,说说最短路算法蕴含的巧妙思想: 每次从当前所有还未标记的结点中选择一个距

UVA - 658 It&#39;s not a Bug, it&#39;s a Feature!

隐式的图搜索,存不下边,所以只有枚举转移就行了,转移的时候判断合法可以用位运算优化, 二进制pre[i][0]表示可以出现的bug,那么u&pre[i][0] == u就表示u是可以出现的bug集合的子集, pre[i][1]表示必须出现的bug,那么u|pre[i][i] != u表示把必须出现的bug添加到u中,u中bug增加,这是不合法的. 正权最短路就dijkstra,用spfa以前某题狂T有阴影.被输出格式坑得不要不要的,如果是if(kas) putchar('\n');就会WA...

【UVA】658 - It&#39;s not a Bug, it&#39;s a Feature!(隐式图 + 位运算)

这题直接隐式图 + 位运算暴力搜出来的,2.5s险过,不是正法,做完这题做的最大收获就是学会了一些位运算的处理方式. 1.将s中二进制第k位变成0的处理方式: s = s & (~(1 << pos)); 将s中二进制第k位变成1的处理方式: s = s | (1 << pos); 2.二进制运算: [1] & : 1 & 1 = 1 , 1 & 0 = 0 , 0 & 0 = 0; 快速判断奇偶性: if(a & 1);//为奇数

uva 10806 Dijkstra, Dijkstra. (最小费最大流)

uva 10806 Dijkstra, Dijkstra. 题目大意:你和你的伙伴想要越狱.你的伙伴先去探路,等你的伙伴到火车站后,他会打电话给你(电话是藏在蛋糕里带进来的),然后你就能够跑去火车站了,那里有人接应你. 可是.由于你的伙伴跑去火车站的时候穿的是囚服,所以,他经过的街道都被戒严了,你必须从其它街道跑过去. 假设你能够到达火车站,请输出你和你的伙伴在路上花费的最短时间,假设不能请"Back to jail". 解题思路:最小费最大流.设置一个超级源点连向监狱(起点1), 容

uva 11367 dijkstra+dp状态压缩

题意:给出n个地点 和 每个地点的油价 ,有 m 条边 , 并给出每条边长度 .1单位汽油可以走1千米  , 油箱的容量为 c , 在初始点 s 时 , 油箱中的油为 0 , 求s 到 t 的最小花费 . 解法: 定义 状态 d[i][j] 表示到达 地点 i 且油箱中有 j 单位油时的最小 花费. 对于状态的转移时 , 有两种方法: 1.把每个点的所有状态都求出 2.不把每个点的状态都求出 , 而是一单位一单位的加油. 对于第一种方法 , 会超时 , 因为每个点的状态太多 , 但是能用的状态就

hdu1818 It&#39;s not a Bug, It&#39;s a Feature!(隐式图最短路径Dijkstra)

题目链接:点击打开链接 题目描述:补丁在修bug时,有时也会引入新的bug,假设有n(n<=20)个潜在的bug和m(m<=100)个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug.第一个串表示打补丁之前的状态('-'表示在该位置不存在bug,'+'表示该位置必须存在bug,0表示无所谓),第二个串表示打补丁之后的状态('-'表示不存在,'+'表示存在,0表示不变).每个补丁都有一个执行时间,你的任务是用最少的时间把一个所有bug都存在的软件通过打补丁的方式变得没