zoukankan      html  css  js  c++  java
  • uva_658_It's not a Bug, it's a Feature!(最短路)

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

    Status

    Description

    Download as PDF

    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 $B= {b_1, b_2, dots, b_n}$ in their software. And they have releasedm patches $p_1, p_2, dots, p_m$. To apply patchpi 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 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$1 le n le 20$ and$1 le m le 100$. 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
    ",++cases);
        if(dist[0]==max_dis)
            printf("Bugs cannot be fixed.
    
    ");
        else
            printf("Fastest sequence takes %d seconds.
    
    ",dist[0]);
    }
    
    int main(){
        while(scanf("%d%d",&n,&m)!=EOF){
            if(!n&&!m) break;
            input();
            solve();
        }return 0;
    }
    


  • 相关阅读:
    Systemd 进程管理器
    Fedora 15 LoveLock的新特性
    fedora 15 iso 硬盘安装
    Linux权限360度赤裸裸华丽丽大曝光连载之二:SetUID
    Linux下socket设置为非阻塞方式和fcntl系统调用
    linux 磁盘 空间 不足 符号链接
    U盘成功安装REHL 6.1
    IT公司中最流行的10种编程语言
    C会否像汇编一样退居幕后?
    白宫决策捕杀拉登现场照片公布
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7082168.html
Copyright © 2011-2022 走看看