链接:

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个补丁,看看是否能打得上。

代码:

 import java.io.*;
import java.util.*;
import static java.util.Arrays.*; public class Main {
Scanner cin = new Scanner(new BufferedInputStream(System.in));
final int INF = 0x3f3f3f3f;
final int UPN = 20;
final int UPM = 100;
int n, m, sec[] = new int[UPM], d[] = new int[1<<UPN];
char before[][] = new char[UPM][UPN], after[][] = new char[UPM][UPN];
boolean done[] = new boolean[1<<UPN]; class Node implements Comparable<Node> {
int s, dist; Node(int s, int dist) {
this.s = s;
this.dist = dist;
} @Override
public int compareTo(Node that) {
return dist - that.dist;
}
} int dijkstra() {
fill(d, INF);
fill(done, false);
int ori = (1<<n) - 1;
PriorityQueue<Node> Q = new PriorityQueue<Node>();
d[ori] = 0;
Q.add(new Node(ori, 0));
while(Q.size() > 0) {
Node cur = Q.poll();
if(cur.s == 0) return cur.dist;
if(done[cur.s]) continue;
done[cur.s] = true;
for(int t = 0; t < m; t++) {
boolean patchable = true;
for(int i = 0; i < n; i++) {
if(before[t][i] == '+' && (cur.s&(1<<i)) == 0) { patchable = false; break; }
else if(before[t][i] == '-' && (cur.s&(1<<i)) > 0) { patchable = false; break; }
}
if(!patchable) continue; Node temp = new Node(cur.s, cur.dist + sec[t]);
for(int i = 0; i < n; i++) {
if(after[t][i] == '+') temp.s |= (1<<i);
else if(after[t][i] == '-') temp.s &= ~(1<<i);
}
if(d[temp.s] > temp.dist) {
d[temp.s] = temp.dist;
Q.add(temp);
}
}
}
return -1;
} void MAIN() {
for(int cases = 1; ; cases++) {
n = cin.nextInt();
m = cin.nextInt();
if(n + m == 0) break;
for(int i = 0; i < m; i++) {
sec[i] = cin.nextInt();
before[i] = cin.next().toCharArray();
after[i] = cin.next().toCharArray();
}
int ans = dijkstra();
System.out.printf("Product %d\n", cases);
if(ans < 0) System.out.printf("Bugs cannot be fixed.\n\n");
else System.out.printf("Fastest sequence takes %d seconds.\n\n", ans);
}
} public static void main(String args[]) { new Main().MAIN(); }
}

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

  1. UVA - 658 It's not a Bug, it's a Feature! (隐式图的最短路,位运算)

    隐式的图搜索,存不下边,所以只有枚举转移就行了,因为bug的存在状态可以用二进制表示,转移的时候判断合法可以用位运算优化, 二进制pre[i][0]表示可以出现的bug,那么u&pre[i][ ...

  2. UVA 658 It's not a Bug, it's a Feature! (最短路,经典)

    题意:有n个bug,有m个补丁,每个补丁有一定的要求(比如某个bug必须存在,某个必须不存在,某些无所谓等等),打完出来后bug还可能变多了呢.但是打补丁是需要时间的,每个补丁耗时不同,那么问题来了: ...

  3. UVA 658 It's not a Bug, it's a Feature!

    这个题目巧妙之处在于用二进制的每个位1,0分别表示bug的有无,以及实施补丁对相应bug的要求以及实施后的对bug的影响. 软件bug的状态:1表示相应bug仍然存在,0表示已经修复.这样可以将软件的 ...

  4. UVa 658 It's not a Bug, it's a Feature! (状态压缩+Dijstra)

    题意:首先给出n和m,表示有n个bug和m个补丁.一开始存在n个bug,用1表示一个bug存在0表示不存在,所以一开始就是n个1,我们的目的是要消除所有的bug, 所以目标状态就是n个0.对于每个补丁 ...

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

    这题直接隐式图 + 位运算暴力搜出来的,2.5s险过,不是正法,做完这题做的最大收获就是学会了一些位运算的处理方式. 1.将s中二进制第k位变成0的处理方式: s = s & (~(1 < ...

  6. 【uva 658】It's not a Bug, it's a Feature!(图论--Dijkstra或spfa算法+二进制表示+类“隐式图搜索”)

    题意:有N个潜在的bug和m个补丁,每个补丁用长为N的字符串表示.首先输入bug数目以及补丁数目.然后就是对M个补丁的描述,共有M行.每行首先是一个整数,表明打该补丁所需要的时间.然后是两个字符串,第 ...

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

    紫书365 题目大意:给你n个全都是bug的东西,然后每次可以修复,给你修复前后的状态,问最后如果能把bug全都修复,最少需要多少时间. 思路:从最初状态开始,然后枚举bug即可. 表示priorit ...

  8. 紫书 例题 11-6 UVa 658 (状态压缩+隐式图搜索+最短路)

    这道题用到了很多知识点, 是一道好题目.      第一用了状态压缩, 因为这里最多只有20位, 所以可以用二进制来储存状态 (要对数据范围敏感), 然后 涉及到了一些位运算.     第二这里是隐式 ...

  9. uva 10274 Fans and Gems(隐式图搜索+模拟)

    Fans and Gems Input: Standard Input Output: Standard Output Tomy's fond of a game called 'Fans and G ...

随机推荐

  1. lighttpd 与 gitweb 搭建服务器

    搭建 Git 仓库服务器 下载 gitweb 如果是用 debian 系的 Linux 发行版,可以使用 apt 下载安装可执行的 gitweb sudo apt-get install gitweb ...

  2. HDU 5694——BD String——————【递归求解】

    BD String Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  3. 常用工具说明--Maven使用说明

    什么是Maven? 如今我们构建一个项目需要用到很多第三方的类库,如写一个使用Spring的Web项目就需要引入大量的jar包.一个项目Jar包的数量之多往往让我们瞠目结舌,并且Jar包之间的关系错综 ...

  4. [转] 多种方法查看Oracle SQL执行计划

    本文转自:http://falchion.iteye.com/blog/616234 一.在线查看执行计划表 如果PLAN_TABLE表不存在,执行$ORACLE_HOME/rdbms/admin/u ...

  5. 樹莓派3B運行.Net Core2.1 Web 項目

    安裝.Net Core 運行時和SDK(非必選) 下載地址 安裝 # 安裝運行時 sudo apt-get -y update # Install the packages necessary for ...

  6. 从服务器下载文件 DownloadServlet()

    .html代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...

  7. javaweb带父标签的自定义标签

    1.完整的示例代码:要实现的功能是父标签中有name属性,子标签将父标签的name属性值打印到jsp页面上. 1.1 父类和子类的标签处理器类 testParentTag.java package c ...

  8. How to limit Dialog's max height?

    1. We can make it to play trick in code. At Dialog's show function, after app has set contentView, w ...

  9. Java并发编程:CountDownLatch、CyclicBarrier和Semaphore (总结)

    下面对上面说的三个辅助类进行一个总结: 1)CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: CountDownLatch一般用于某个线程A等待 ...

  10. C#打印代码运行时间

    使用以下方法可以准确的记录代码运行的耗时. System.Diagnostics.Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); / ...