Uva 658 - It's not a Bug, it's a Feature! (最短路)

题目链接 https://vjudge.net/problem/UVA-658

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

【思路】
位运算+最短路,很经典的一道题目,用n为二进制串来表示一种状态,0表示该处没有bug,1表示有,把状态转移所消耗的时间看成路径长度,那么初始状态即一个全1的串,时间为0,要根据现有的m个补丁看看能不能走到二进制串全为0的状态,对dijkstra算法稍作变型即可,每次都枚举所有的补丁,判断当前状态下能否打这个补丁,如果能就进行状态转移,这样只要出现了串为全0的状态说明能把所有bug都消除,否则就无法消除所有bug.

#include<bits/stdc++.h>
using namespace std;

const int maxn = (1 << 20) + 10;
const int maxm = 105;

int n, m, mintime;
bool done[maxn];

struct node {
    int time;//耗时(当作路径长度)
    int a1, a2, b1, b2;//表示修复前后状态的二进制串
    //a1修复前为1,a2修复前为0,b1修复后为1,b2修复后为0
}a[maxm];

struct HeapNode {
    int u, d;
    HeapNode(int uu, int dd) :u(uu), d(dd) {}
    bool operator < (const HeapNode& rhs) const {
        return d > rhs.d;
    }
};

void init() {
    memset(done, 0, sizeof(done));
    for (int i = 0; i <= m; ++i) a[i].time = a[i].a1 = a[i].a2 = a[i].b1 = a[i].b2 = 0;
}

bool dijkstra() {
    priority_queue<HeapNode> que;
    que.push(HeapNode((1 << n) - 1, 0));//初始时的状态,全为1表示bug都存在

    while (!que.empty()) {
        HeapNode x = que.top();
        que.pop();
        int u = x.u;
        if (u == 0) { mintime = x.d; return true; }
        if (done[u]) continue;
        done[u] = true;

        for (int i = 0; i < m; ++i) {//每次遍历所有的补丁,看能不能往上打
            if ((u & a[i].a1) == a[i].a1 && (~u & a[i].a2) == a[i].a2) {//符合要求就打,计算出下一个状态,加入队列
                int uu = u | a[i].b1;
                uu = uu & ~a[i].b2;
                que.push(HeapNode(uu, x.d + a[i].time));
            }
        }
    }
    return false;
}

int main() {
    int kase = 0;
    while (scanf("%d%d", &n, &m) == 2) {
        if (!n && !m) break;
        init();
        for (int i = 0; i < m; ++i) {
            int t;
            char s1[30], s2[30];
            scanf("%d%s%s", &t, s1, s2);
            for (int j = 0; j < n; ++j) {
                a[i].time = t;
                if ('+' == s1[n - 1 - j]) { a[i].a1 = a[i].a1 | (1 << j); }
                if ('-' == s1[n - 1 - j]) { a[i].a2 = a[i].a2 | (1 << j); }
                if ('+' == s2[n - 1 - j]) { a[i].b1 = a[i].b1 | (1 << j); }
                if ('-' == s2[n - 1 - j]) { a[i].b2 = a[i].b2 | (1 << j); }
            }
        }

        /*for (int i = 0; i < m; ++i) {
            printf("%d %d %d %d\n", a[i].a1, a[i].a2, a[i].b1, a[i].b2);
        }*/

        printf("Product %d\n", ++kase);
        if (dijkstra()) {
            printf("Fastest sequence takes %d seconds.\n", mintime);
        }
        else {
            puts("Bugs cannot be fixed.");
        }
        putchar('\n');
    }
    return 0;
}
posted @ 2018-02-04 12:43  不想吃WA的咸鱼  阅读(225)  评论(0编辑  收藏  举报