uva_658_It's not a Bug, it's a Feature!(最短路)

It‘s not a Bug, it‘s a Feature!

Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu

SubmitStatus

Description

It is a curious fact that consumers buying a new software product generally donot expect the software to be bug-free. Can you imagine buying a car whose steering wheel only turns to the right? Or a CD-player that plays only CDs with country music
on them? Probably not. But for software systems it seems to be acceptable if they do not perform as they should do. In fact, many software companies have adopted the habit of sending out patches to fix bugs every few weeks after a new product is released (and
even charging money for the patches).

Tinyware Inc. is one of those companies. After releasing a new word processing software this summer, they have been producing patches ever since. Only this weekend they have realized a big problem with the patches they released. While all patches fix some
bugs, they often rely on other bugs to be present to be installed. This happens because to fix one bug, the patches exploit the special behavior of the program due to another bug.

More formally, the situation looks like this. Tinyware has found a total of
n
bugs in their software. And they have releasedm patches
. To apply patchpi to the software, the bugs
have to be present in the software, and the bugs
must be absent (of course
holds). The patch then fixes the bugs (if they have been present) and introduces the new bugs
(where, again,).

Tinyware‘s problem is a simple one. Given the original version of their software, which contains all the bugs inB, it is possible to apply a sequence of patches to the software which results in a bug- free version of the software? And if so, assuming
that every patch takes a certain time to apply, how long does the fastest sequence take?

Input

The input contains several product descriptions. Each description starts with a line containing two integersn and
m, the number of bugs and patches, respectively. These values satisfy and.
This is followed bym lines describing the m patches in order. Each line contains an integer, the time in seconds it takes to apply the patch, and two strings ofn characters each.

The first of these strings describes the bugs that have to be present or absent before the patch can be applied. Thei-th position of that string is a ``+‘‘ if bug
bi has to be present, a ``-‘‘ if bugbi has to be absent, and a `` 0‘‘ if it doesn‘t matter whether the bug is present or not.

The second string describes which bugs are fixed and introduced by the patch. Thei-th position of that string is a ``+‘‘ if bug
bi is introduced by the patch, a ``-‘‘ if bugbi is removed by the patch (if it was present), and a ``0‘‘ if bugbi is not affected by the patch (if it was
present before, it still is, if it wasn‘t, is still isn‘t).

The input is terminated by a description starting with n = m = 0. This test case should not be processed.

Output

For each product description first output the number of the product. Then output whether there is a sequence of patches that removes all bugs from a product that has alln bugs. Note that in such a sequence a patch may be used multiple times. If there
is such a sequence, output the time taken by the fastest sequence in the format shown in the sample output. If there is no such sequence, output ``Bugs cannot be fixed.‘‘.

Print a blank line after each test case.

Sample Input

3 3
1 000 00-
1 00- 0-+
2 0-- -++
4 1
7 0-0+ ----
0 0

Sample Output

Product 1
Fastest sequence takes 8 seconds.

Product 2
Bugs cannot be fixed.

题意:补丁在修补bug时,有时候会引入新的bug。假定有n(n<=20)个潜在bug和m(m<=100)个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug。第一个串表示打补丁前的状态(“-”表示该bug必须不存在,“+”表示必须存在,“0”表示无所谓),第二个串表示打补丁后的状态(“-”表示不存在,“+”表示存在,“0”表示不变)。每个补丁都有一个执行时间,你的任务是用最少的时间把一个所有bug都存在的软件通过打补丁的方式变得没有bug。一个补丁可以打多次。

分析:最短路。把状态看做结点,状态转移看做边,然后用spfa求解即可。结点数很多,多达2^n个,并且很多状态碰不到,所以不需要先把图存好,每次取出一个结点,直接枚举m个补丁,看是否能够打得上。

注:状态可以用二进制存。题目中巧妙运用位运算。

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=22169

代码清单:

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<cctype>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

const int maxs = 20 + 5;
const int maxm = 100 + 5;
const int maxn = (1<<20) + 5;
const int max_dis = 0x7f7f7f7f;

struct Patch{
    int dis;
    char s1[maxs];
    char s2[maxs];
}patch[maxm];

int n,m,cases;
int dist[maxn];
bool vis[maxn];

void input(){
    for(int i=1;i<=m;i++){
        scanf("%d%s%s",&patch[i].dis,patch[i].s1,patch[i].s2);
    }
}

//判断该补丁是否可用
bool useful(int u,int idx){
    for(int i=n-1;i>=0;i--){
        int idd=(u>>(n-i-1))&1;
        if(patch[idx].s1[i]=='-'&&idd==1)
            return false;
        if(patch[idx].s1[i]=='+'&&idd==0)
            return false;
    }return true;
}

//得到打完补丁后的状态
int get_v(int u,int idx){
    int vv=0;
    for(int i=n-1;i>=0;i--){
        int idd=(u>>(n-i-1))&1;
        if(patch[idx].s2[i]=='0'){
            if(idd==1) vv+=(1<<(n-i-1));
        }
        if(patch[idx].s2[i]=='+'){
            vv+=(1<<(n-i-1));
        }
    }return vv;
}

int spfa(){
    int s=(1<<n)-1;
    memset(vis,false,sizeof(vis));
    memset(dist,max_dis,sizeof(dist)); //cout<<max_dis<<" "<<dist[0]<<endl;
    dist[s]=0; vis[s]=true;
    queue<int>que;
    while(!que.empty()) que.pop();
    que.push(s);
    while(!que.empty()){
        int u=que.front();
        que.pop(); vis[u]=false;
        for(int i=1;i<=m;i++){
            if(useful(u,i)){
                int v=get_v(u,i);
                if(dist[v]>dist[u]+patch[i].dis){
                    dist[v]=dist[u]+patch[i].dis;
                    if(!vis[v]){
                        vis[v]=true;
                        que.push(v);
                    }
                }
            }
        }
    }
}

void solve(){
    spfa();
    printf("Product %d\n",++cases);
    if(dist[0]==max_dis)
        printf("Bugs cannot be fixed.\n\n");
    else
        printf("Fastest sequence takes %d seconds.\n\n",dist[0]);
}

int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        if(!n&&!m) break;
        input();
        solve();
    }return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

uva_658_It's not a Bug, it's a Feature!(最短路)

时间: 2024-10-08 09:48:15

uva_658_It's not a Bug, it's a Feature!(最短路)的相关文章

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

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

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

【HDOJ】1818 It&#39;s not a Bug, It&#39;s a Feature!

状态压缩+优先级bfs. 1 /* 1818 */ 2 #include <iostream> 3 #include <queue> 4 #include <cstdio> 5 #include <cstring> 6 #include <cstdlib> 7 #include <algorithm> 8 using namespace std; 9 10 #define MAXM 105 11 12 typedef struct {

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&#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

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

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

题意: 有n个BUG和m个补丁,每个补丁用一个串表示打补丁前的状态要满足的要求,第二个串表示打完后对补丁的影响,还有打补丁所需要的时间. 求修复所有BUG的最短时间. 分析: 可以用n个二进制位表示这n个BUG的当前状态.最开始时所有BUG都存在,所以状态为n个1.目标状态是0 当打上一个补丁时,状态就会发生转移.因为有可能一个补丁要打多次,所以这个图不是DAG. 可以用Dijkstra算法,求起始状态到终态的最短路.代码中用了优先队列优化. 1 #include <cstdio> 2 #in

POJ 1482 It&#39;s not a Bug, It&#39;s a Feature! 状压+spfa

http://poj.org/problem?id=1482 题意:先黑了一发程序猿,说软件总是有漏洞,然后打补丁拆了东墙补西墙.现在软件有不超过20个漏洞,有不超过100个补丁,每个补丁有运用条件(某些漏洞不能存在,某些漏洞必须存在)和作用效果(补漏洞,产生新漏洞),已经安装时间,开始有所有漏洞,问是否有一种安装补丁的顺序能填补所有漏洞,并求最短的时间. 分析:因为只有20个漏洞,所以可以状压,大概100万的级别,每位为0表示没有这个漏洞,为1表示有这个漏洞.记f[i]表示达到状态i所需最短时