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 }

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

原文地址:https://www.cnblogs.com/hkxy125/p/9532356.html

时间: 2024-08-01 00:19:21

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

【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 - 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! (单源最短路,dijkstra+优先队列,变形,经典)

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

UVA - 658 It’s not a Bug, it’s a Feature!(优先队列Dijkstra)

题目链接 题目大意:补丁和漏洞之间的修复问题.有n种漏洞,m种补丁,接着给你m行代表的是m种补丁使用的情况.前面的n个字符表示的是补丁的使用前提,后面的n个字符表示的是补丁使用完后的漏洞状况.字符'0'代表的是这个漏洞存不存在都没关系,'+'代表的是这个漏洞存在或者出现, '-'代表的是消失或者是不存在.使用每种补丁都需要时间,一开始这些漏洞都是存在的,问最少花多少的时间能够把这些漏洞都消灭. 解题思路:因为有'0'这样的情况,所以需要把不确定的情况暴力的转化为确定的情况,然后用2进制数来表示目

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

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

UVa658 It&#39;s not a Bug, it&#39;s a Feature! (最短路,隐式图搜索)

链接:http://vjudge.net/problem/UVA-658 分析:Dijkstra求隐式图最短路. 1 #include <cstdio> 2 #include <queue> 3 using namespace std; 4 5 const int maxn = 20; 6 const int maxm = 100 + 5; 7 const int INF = 1000000000; 8 9 int n, m, t[maxm], vis[1 << max

状态转移的最短路 隐式图搜索 UVA 658

紫书365 题目大意:给你n个全都是bug的东西,然后每次可以修复,给你修复前后的状态,问最后如果能把bug全都修复,最少需要多少时间. 思路:从最初状态开始,然后枚举bug即可. 表示priority里面的bool operator和单纯的sort的定义的大小于号是不一样的啊,如果你想用sort来计算struct从小到大的的话是这样的 struct Node{ int bugs, dist; bool operator < (const Node &a) const{ return dis

UVA - 10603 Fill(隐式图搜索)

题目大意:经典的倒水问题.给你三个瓶子,体积为a,b,c. 刚开始a,b是空的,c是满的,现在要求你到出体积为d的水.倒水的规则为,要么倒水方为空,要么接水方满 问倒到容量为d时,倒水的最小体积是多少,如果不能倒出体积为d的水,找出d' < d,最接近d的d'和最小的体积 解题思路:刚才时以为直接bfs,用vis标记一下就结束了,结果WA了.为什么会WA,因为我这样求的是倒水次数最少的,而不是倒水体积最小的,WA是肯定的了 接着将vis数组改成int型的,纪录达到这个状态时倒水的体积,结果可想而

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都存在的软件通过打补丁的方式变得没