UVA - 658 It’s not a Bug, it’s a Feature!(优先队列Dijkstra)

题目链接

题目大意:补丁和漏洞之间的修复问题。有n种漏洞,m种补丁,接着给你m行代表的是m种补丁使用的情况。前面的n个字符表示的是补丁的使用前提,后面的n个字符表示的是补丁使用完后的漏洞状况。字符‘0’代表的是这个漏洞存不存在都没关系,‘+’代表的是这个漏洞存在或者出现, ‘-’代表的是消失或者是不存在。使用每种补丁都需要时间,一开始这些漏洞都是存在的,问最少花多少的时间能够把这些漏洞都消灭。

解题思路:因为有‘0’这样的情况,所以需要把不确定的情况暴力的转化为确定的情况,然后用2进制数来表示目前漏洞的状态,‘-’用1代表。’+‘用0代表。转化成0到2^n - 1的最短路问题。

代码:

#include <cstdio>
#include <queue>
#include <vector>

using namespace std;

typedef pair<int, int> pii;
priority_queue<pii, vector<pii>, greater<pii> > q;

const int maxn = 25;
const int maxm = (1<<20) + 5;
const int INF = 0x3f3f3f3f;

struct State {

    int u;
    int d;
};

vector<State> G[maxm];

char st1[maxn], st2[maxn];
int d[maxm];

int change (int n, char* st) {

    int ans = 0;
    for (int i = 0; i < n; i++) {

        ans = (ans<<1);
        if (st[i] == ‘-‘)
            ans |= 1;
    }
    return ans;
}

void add_bug (int num1, int num2, int d) {

     State st;
     st.u = num2;
     st.d = d;
     G[num1].push_back(st);
}

inline void dfs (int n, int k, int t) {

    if (k == n) {
         int num1 = change(n, st1);
         int num2 = change(n, st2);
         add_bug(num1, num2, t);
         return;
    }

    char tmp;
    if (st1[k] == ‘0‘) {

        st1[k] = ‘-‘;
        tmp = st2[k];
        if (st2[k] == ‘0‘)
            st2[k] = ‘-‘;
        dfs(n, k + 1, t);
        st2[k] = tmp;

        st1[k] = ‘+‘;
        tmp = st2[k];
        if (st2[k] == ‘0‘)
            st2[k] = ‘+‘;
        dfs(n, k + 1, t);
        st2[k] = tmp;

        st1[k] = ‘0‘;

    } else {

        tmp = st2[k];
        if (st2[k] == ‘0‘)
            st2[k] = st1[k];
        dfs(n, k + 1, t);
        st2[k] = tmp;
    }
}

void read_Graph (int n, int m) {

    int t;
    int T = 1 << n;
    for (int i = 0; i < T; i++)
        G[i].clear();
    for (int i = 0; i < m; i++) {

        scanf ("%d%s%s", &t, st1, st2);
        dfs(n, 0, t);
    }
}

int Dijkstra (int n) {

    int T = 1 << n;
    for (int i = 1; i < T; i++)
        d[i] = INF;
    d[0] = 0;

    q.push(make_pair(d[0], 0));

    pii cur;
    int u, v, w;

    while (!q.empty()) {

        cur = q.top();
        q.pop();

        u = cur.second;
        if (cur.first != d[u]) continue;
        for (int i = 0; i < G[u].size(); i++) {
            v = G[u][i].u;
            w = G[u][i].d;
            if (d[v] > d[u] + w) {
                d[v] = d[u] + w;
                q.push(make_pair(d[v], v));
            }
        }
    }

    return d[T-1];
}

int main () {

    int n, m, cas = 0;
    printf ("%d\n", INF);
    while (scanf ("%d%d", &n, &m) && (n || m)) {

        read_Graph(n, m);
        int ans = Dijkstra(n);

        printf ("Product %d\n", ++cas);
        if (ans == INF)
            printf ("Bugs cannot be fixed.\n\n");
        else
            printf ("Fastest sequence takes %d seconds.\n\n", ans);
    }
    return 0;
}
时间: 2024-08-24 01:19:02

UVA - 658 It’s not a Bug, it’s a Feature!(优先队列Dijkstra)的相关文章

UVa 658 - It&#39;s not a Bug, it&#39;s a Feature!(Dijkstra + 隐式图搜索)

链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=599 题意: 补丁在修正bug时,有时也会引入新的bug.假定有n(n≤20)个潜在bug和m(m≤100)个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug.第一个串表示打补丁之前的状态("-"表示该bug必须不存在,"+&

UVA - 658 It&#39;s not a Bug, it&#39;s a Feature!

隐式的图搜索,存不下边,所以只有枚举转移就行了,转移的时候判断合法可以用位运算优化, 二进制pre[i][0]表示可以出现的bug,那么u&pre[i][0] == u就表示u是可以出现的bug集合的子集, pre[i][1]表示必须出现的bug,那么u|pre[i][i] != u表示把必须出现的bug添加到u中,u中bug增加,这是不合法的. 正权最短路就dijkstra,用spfa以前某题狂T有阴影.被输出格式坑得不要不要的,如果是if(kas) putchar('\n');就会WA...

UVA 658 It&#39;s not a Bug, it&#39;s a Feature! (单源最短路,dijkstra+优先队列,变形,经典)

题意:有n个bug,有m个补丁,每个补丁有一定的要求(比如某个bug必须存在,某个必须不存在,某些无所谓等等),打完出来后bug还可能变多了呢.但是打补丁是需要时间的,每个补丁耗时不同,那么问题来了:要打多久才能无bug?(同1补丁可重复打) 分析: n<=20,那么用位来表示bug的话有220=100万多一点.不用建图了,图实在太大了,用位图又不好玩.那么直接用隐式图搜索(在任意点,只要满足转移条件,任何状态都能转). 但是有没有可能每个状态都要搜1次啊?那可能是100万*100万啊,这样出题

658 - It&#39;s not a Bug, it&#39;s a Feature! (Dijkstra算法)

今天第一次系统的学习了一下最短路算法,开始刷第十一章,第一次写Dijkstra算法,出现了很多喜闻乐见的错误..而且uva上样例很水,瓢虫也很水 ,坑了我好久. 首先是对于结点的处理,我们必须要维护一个二元组,一个表示结点一个表示当前结点最短路.   因为Dijkstra算法利用了优先队列来加速算法,所以需要定义小于运算符,一开始我直接将状态装进了优先队列,显然是不对的,因为优先队列的作用就是取出当前距离最短的结点. 其次,说说最短路算法蕴含的巧妙思想: 每次从当前所有还未标记的结点中选择一个距

【UVA】658 - It&#39;s not a Bug, it&#39;s a Feature!(隐式图 + 位运算)

这题直接隐式图 + 位运算暴力搜出来的,2.5s险过,不是正法,做完这题做的最大收获就是学会了一些位运算的处理方式. 1.将s中二进制第k位变成0的处理方式: s = s & (~(1 << pos)); 将s中二进制第k位变成1的处理方式: s = s | (1 << pos); 2.二进制运算: [1] & : 1 & 1 = 1 , 1 & 0 = 0 , 0 & 0 = 0; 快速判断奇偶性: if(a & 1);//为奇数

【uva 658】It&#39;s not a Bug, it&#39;s a Feature!(图论--Dijkstra算法+二进制表示)

题意:有n个潜在的bug和m个补丁,每个补丁用长为n的字符串表示.首先输入bug数目以及补丁数目.然后就是对m 个补丁的描述,共有m行.每行首先是一个整数,表明打该补丁所需要的时间.然后是两个字符串,地一个字符串 是对软件的描述,只有软件处于该状态下才能打该补丁该字符串的每一个位置代表bug状态(-代表该位置没bug,+代 表该位置有bug,0表示该位置无论有没有bug都可打补丁).然后第二个字符串是对打上补丁后软件状态的描述 -代表该位置上的bug已经被修复,+表示该位置又引入了一个新的bug

UVa 658 (Dijkstra) It&#39;s not a Bug, it&#39;s a Feature!

题意: 有n个BUG和m个补丁,每个补丁用一个串表示打补丁前的状态要满足的要求,第二个串表示打完后对补丁的影响,还有打补丁所需要的时间. 求修复所有BUG的最短时间. 分析: 可以用n个二进制位表示这n个BUG的当前状态.最开始时所有BUG都存在,所以状态为n个1.目标状态是0 当打上一个补丁时,状态就会发生转移.因为有可能一个补丁要打多次,所以这个图不是DAG. 可以用Dijkstra算法,求起始状态到终态的最短路.代码中用了优先队列优化. 1 #include <cstdio> 2 #in

【HDOJ】1818 It&#39;s not a Bug, It&#39;s a Feature!

状态压缩+优先级bfs. 1 /* 1818 */ 2 #include <iostream> 3 #include <queue> 4 #include <cstdio> 5 #include <cstring> 6 #include <cstdlib> 7 #include <algorithm> 8 using namespace std; 9 10 #define MAXM 105 11 12 typedef struct {

hdu1818 It&#39;s not a Bug, It&#39;s a Feature!(隐式图最短路径Dijkstra)

题目链接:点击打开链接 题目描述:补丁在修bug时,有时也会引入新的bug,假设有n(n<=20)个潜在的bug和m(m<=100)个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug.第一个串表示打补丁之前的状态('-'表示在该位置不存在bug,'+'表示该位置必须存在bug,0表示无所谓),第二个串表示打补丁之后的状态('-'表示不存在,'+'表示存在,0表示不变).每个补丁都有一个执行时间,你的任务是用最少的时间把一个所有bug都存在的软件通过打补丁的方式变得没