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

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 = {b1, b2, . . . , bn}
in their software. And they have released m patches p1, p2, . . . , pm. To apply patch pi to the software,
the bugs B
+
i ⊆ B have to be present in the software, and the bugs B

i ⊆ B must be absent (of course
B
+
i ∩B

i = ∅ holds). The patch then fixes the bugs F

i ⊆ B (if they have been present) and introduces
the new bugs F
+
i ⊆ B (where, again, F

i ∩ B

i = ∅).
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 ≤ n ≤ 20 and
1 ≤ m ≤ 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.

在任意时刻,一个bug可能存在也可能不存在,所以可以用一个n位的二进制串表示当前软件的“状态”。打完补丁之后,bug状态发生变化,对应“状态转移”。 然而并不是动态规划,将每种状态看成节点,状态转移看成边,转化成最短路问题,然后使用Dijkstra或者Bellman-Ford算法求解。
需注意:本题应采用隐式图搜索,对于每个节点u,我们遍历到的时候不是去读G[u],而是直接枚举m种补丁,检查是否能得到新的有用节点。

#include 
#include 
#include 
#include 
#include 

using namespace std;
const int MAXBUG = 20;
const int MAXPatch = 105;
int n,m,t[MAXPatch],dis[1 << MAXBUG],vis[1 << MAXBUG];
char before[MAXPatch][MAXBUG + 5],after[MAXPatch][MAXBUG + 5];
const int INF = 0x3f3f3f3f;
/*
 * 隐式网络图搜索
 * 本质是搜索 是最短路
 * */
struct Node{
    int bug,dist;
    bool operator < (const Node &a) const {
        return dist > a.dist;
    }
};

int Dijkstra() {
    for(int i=0; i<(1<<n); i++) {
        vis[i] = 0;
        dis[i] = INF;
    }
    priority_queue<Node> q;
    Node start;
    start.bug = (1<<n) - 1;
    start.dist = 0;
    q.push(start);
    dis[start.bug] = 0;
    while(!q.empty()) {
        Node x = q.top(); q.pop();
        if(x.bug == 0) return x.dist;
        if(vis[x.bug]) continue;
        vis[x.bug] = 1;
        for(int i=0; i<m; i++) {
            bool patchable = true;
            for(int j=0; j<n; j++) {
                if(before[i][j] == '-' && (x.bug & (1<<j))) { patchable = false; break; }//不能有但是有
                if(before[i][j] == '+' && !(x.bug & (1<<j))) { patchable = false; break; }//需要有 但是没有
            }
            if(patchable == false) continue;
            Node nxt;
            nxt.bug = x.bug;
            nxt.dist = x.dist + t[i];
            for(int j=0; j<n; j++) {
                if(after[i][j] == '-') nxt.bug &= ~(1<<j);// after j位 没有
                if(after[i][j] == '+') nxt.bug |= (1<<j);// after j位 有
            }
            int &Dist = dis[nxt.bug];
            //nxt  大于现有状态  没有必要入队
            if(nxt.dist < Dist) {
                Dist = nxt.dist;
                q.push(nxt);
            }
        }
    }
    return -1;
}

int main() {
    int kase = 0;
    while(scanf("%dis %dis",&n,&m) == 2 && n) {
        for(int i=0; i<m; i++)
            scanf("%dis %s %s",&t[i],before[i],after[i]);
        int Ans = Dijkstra();
        printf("Product %dis\n", ++kase);
        if(Ans < 0) printf("Bugs cannot be fixed.\n\n");    //需要注意题目要求的输出格式
        else printf("Fastest sequence takes %dis seconds.\n\n", Ans);
    }
    return 0;
}

你可能感兴趣的:(UVa,图论)