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

来源:互联网 发布:wpf 数据绑定 编辑:程序博客网 时间:2024/05/24 02:58

题意:

某个软件有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 <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <cstdlib>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<Node> 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<<n)-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<<n)-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;}
0 0
原创粉丝点击