UVA 658 - It's not a Bug, it's a Feature!(dijkstra+优先队列)

题意:

某个软件有n个漏洞m的补丁,而每个补丁修复漏洞有前提条件,即有些漏洞必须存在或不存在,每个补丁的修复时间各不相同,现在有n个漏洞,让你求出把这n个漏洞全部修复所花的最少时间。

解析:

这个题目可以转化为最短路的模型来求解。由n个1或0来表示bug,我们很容易联想要二进制和十进制的转化,对于当前的bug状态,我们可以转化为1个十进制来表示,那么一开始的状态显然就是2^n-1,目标状态就是0,也就是从2^n-1转化为0,用时最少,相当于从2^n-1到0的最短路

对于一个补丁,其实就是一些有向边(是有向边,而且不是一条,可能是多条,所以是一些),为什么?因为对于当前的bug状态我们转化为十进制u,扫描所有的补丁,找到可以使用的补丁,并在这个补丁作用下变为一个新的bug状态,这个新的bug状态也对应一个十进制v,所以其实就是u到v,有向边u–>v,边权就是使用补丁使用的时间。

一种思路是先建图,再来一个最短路,但是会超时,因为图的顶点太多,边也很多。n的上限是20,即顶点个数为2^20-1,而边数在最坏情况下很大的,一定会超时。而我们思考可以知道,很多顶点是不一定会经过的,也就是很多bug的状态不会出现,所以我们为什么不一边最短路一边建图呢?所以我们可以就用dijkstra+优先队列的做法来求解。

my code

#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 105;
const int MAXN = (1<<21) + 10;
int n, m;

struct Oper {
    char from[25], to[25];
    int val;
}op[N];

struct Node {
    int u, dist;
    friend bool operator < (Node a, Node b) {
        return a.dist > b.dist;
    }
};

bool vis[MAXN];
int d[MAXN];
priority_queue que;

void init() {
    memset(vis, false, sizeof(vis));
    memset(d, INF, sizeof(d));
    while(!que.empty()) que.pop();
}

bool judge(int state, Oper oper) {
    for(int i = n-1, j = 0; i >= 0; i--, j++) {
        if(oper.from[i] == '-') {
            if((state >> j & 1) != 0)
                return false;
        }else if(oper.from[i] == '+') {
            if((state >> j & 1) != 1)
                return false;
        } 
    }
    return true;
}

int trans(int state, Oper oper) {
    int full = (1<1;
    for(int i = n-1, j = 0; i >= 0; i--, j++) {
        if(oper.to[i] == '+') {
            state |= (1 << j);
        }else if(oper.to[i] == '-') {
            state &= (full-(1 << j));
        }
    }
    return state;
}

int spfa(int start) {
    d[start] = 0;
    que.push((Node){start, d[start]});

    while(!que.empty()) {
        Node node = que.top();
        que.pop();

        int u = node.u;
        if(vis[u]) continue;
        vis[u] = true;

        for(int i = 0; i < m; i++) {
            if(judge(u, op[i])) {
                int v = trans(u, op[i]);
                if(d[v] > d[u] + op[i].val) {
                    d[v] = d[u] + op[i].val;
                    que.push((Node){v, d[v]});
                }
            }
        }
    }
    return d[0];
}

int main() {
    int cas = 1;
    while(scanf("%d%d", &n, &m) != EOF && (n || m)) {
        init();
        for(int i = 0; i < m; i++) {
            scanf("%d%s%s", &op[i].val, op[i].from, op[i].to);
        }

        int ans = spfa((1<1);
        printf("Product %d\n", cas++);
        if(ans == INF) {
            puts("Bugs cannot be fixed.");
        }else {
            printf("Fastest sequence takes %d seconds.\n", ans);
        }
        puts("");
    }
    return 0;
}

你可能感兴趣的:(最短路,uva,658)