链接:

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. CF 675D——Tree Construction——————【二叉搜索树、STL】

    D. Tree Construction time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  2. java服务器访问其他服务器工具类编写

    java服务器访问其他服务器工具类编写适合各种消息推送及微服务交互 package com.xiruo.medbid.components; import com.xiruo.medbid.util. ...

  3. Magento 2中文手册教程 - 如何获得 Magento 2

    Magento 2 安装 我们搜集了一些信息来帮助您开始使用Magento 2和你的Magento 2安装. 我们有一些资源帮助您开始使用Magento 2. 如何获得 Magento 2 参考下表开 ...

  4. 如何学习OpenStack

    转自:http://www.chenshake.com/learn-how-openstack/ 如何学习OpenStack 由于工作的关系,也招收实习生,希望可以通过实习生的培养,让他们对Opens ...

  5. java 并发 (四) ---- 并发容器

    Hashmap 和 Concurrenthashmap Hashmap 不适合并发,应该使用ConcurrentHashMap . 这是很多人都知道的,但是为什么呢? 可以先看一下这两篇文章. JDK ...

  6. Spring 中任意位置获取 session 和 request

    在web.xml中添加监听: <listener> <listener-class>org.springframework.web.context.ContextLoaderL ...

  7. 百度富文本Ueditor将图片存在项目外路径并回显

    我的毕设中需要一个类似新闻发布的功能,使用到百度富文本编辑器,不过百度富文本编辑器有点坑(只是我太菜了),粘贴图片和回显这个坑坑了我两天时间.效果是这样的: 就是可以在文本中粘贴图片并显示出来,直接说 ...

  8. docker 开机自动启动容器

    注意:如果有存在多个容器,都占用了同一端口,那么只会起来一个,要注意,我在调试时候就遇到这个坑了 在使用docker run启动容器时,使用--restart参数来设置: docker run -m  ...

  9. sqlserver查询表字段描述(转)

    原文地址:https://blog.csdn.net/changhong009/article/details/29587063 --快速查看表结构(比较全面的) SELECT CASE WHEN c ...

  10. jQuery Text-to-Speech 谷歌在线语音

    <!DOCTYPE html> <html> <head> <meta content="text/html; charset=utf-8" ...