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:0KB    64bit IO Format:%lld & %llu

Description

Download as PDF

It is a curious fact that consumers buying a new software product generally do not 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 $B= \{b_1, b_2, \dots, b_n\}$ in their software. And they have released m patches $p_1, p_2, \dots, p_m$. To apply patch pi to the software, the bugs $B^+_i \subseteq B$ have to be present in the software, and the bugs $B^-_i \subseteq B$ must be absent (of course $B^+_i \cap B^-_i = \emptyset$ holds). The patch then fixes the bugs $F^-_i \subseteq B$ (if they have been present) and introduces the new bugs $F^+_i \subseteq B$ (where, again, $F^-_i \cap B^-_i = \emptyset$).

Tinyware's problem is a simple one. Given the original version of their software, which contains all the bugs in B, 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 integers n and m, the number of bugs and patches, respectively. These values satisfy $1 \le n \le 20$ and $1 \le m \le 100$. This is followed by m 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 of n characters each.

The first of these strings describes the bugs that have to be present or absent before the patch can be applied. The i-th position of that string is a ``+'' if bug bi has to be present, a ``-'' if bug bi 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. The i-th position of that string is a ``+'' if bug bi is introduced by the patch, a ``-'' if bug bi is removed by the patch (if it was present), and a ``0'' if bug bi 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 all n 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.


题意:系统打补丁时的规则是这样的:打上一个补丁,可能会产生其他漏洞,现在给出补丁和打完这个补丁之后的情况和打补丁花费的时间,要求你在最短的时间内修复所有漏洞(一个补丁可以多次使用);


其中 0 代表这个漏洞可有可无 + 代表这个漏洞必须存在才能打上这个补丁 - 代表这这漏洞必须不存在才能打上这个漏洞

一开始所有漏洞都存在即串的所有字符都为‘+’


分析:

*   首先将所有进字符串和出字符串保存下来,由于每个补丁最多存在两种状态即存在和不存在,那么我们可以将‘+’表示为1,‘-’ 表示为0
*   字符串长度上限为20,2^20为1048576,用int数组能够存下,那么此时每个字符串就对应了一个唯一确定的数字。
*   然而此时最多会有100对字符串,如果暴力跑dfs建立每个可能的进串对应每个可能的出串,建立一张完整的图,然后跑单源最短路,这样很明显会超时(亲测不行 T_T)


*   实际上这题的做法是一个隐式图搜索,即不去建立一张完完整整的图,而是当需要得到某个结点u出发的所有边时,不是去读G【u】,而是直接枚举所有进出串,看是否可行。这样以来就避免了上面方法的图中一些根本不可能到达的边的浪费,由于m最大只有100,所以时间也不会超。

*   鄙人的做法是用二进制保存每一个数,对比是也用二进制对比,跑一边spfa求单源最短路,时间上2s++,。


#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 1050000
#define maxm 105

int n,m;
char u[maxm][25],v[maxm][25];
int w[maxm];

int shoot;
int aim;
int d[maxn];
int que[maxn];
bool vis[maxn];

bool meet(int j,int k)
{
    for(int i=0;i<n;i++)
    {
        if(u[j][i]=='+'&&!(k%2)) return false;
        if(u[j][i]=='-'&&(k%2)) return false;
        k/=2;
    }
    return true;
}

int trans(int j,int k)
{
    int ans=0;
    for(int i=0;i<n;i++)
    {
        if(v[j][i]=='0')
        {
            if(k%2) ans+=(1<<i);
        }
        else if(v[j][i]=='+') ans+=(1<<i);
        k/=2;
    }
    return ans;
}

int spfa()
{
   memset(d,0x3f,sizeof d);
   memset(vis,false, sizeof vis);

   shoot=0;
   for(int i=0;i<n;i++) shoot+=(1<<i);
   int f=0,r=-1;
   que[++r]=shoot;
   d[shoot]=0;

   while(f<=r)
   {
        int k=que[f++];
        vis[k]=false;

        for(int i=1;i<=m;i++)
        {
            if(meet(i,k))
            {
                int x=trans(i,k);
                if(d[k]+w[i]<d[x])
                {
                    d[x]=d[k]+w[i];
                    if(!vis[x])
                    {
                        que[++r]=x;
                        vis[x]=true;
                    }
                }
            }
        }
   }
   return d[0];
}


int main()
{
    int c=1;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(!n&&!m) break;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%s%s",&w[i],u[i],&v[i]);
        }

        int flag=spfa();

        printf("Product %d\n",c++);
        if(flag==INF) printf("Bugs cannot be fixed.\n");
        else printf("Fastest sequence takes %d seconds.\n",flag);
        puts("");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值