uva658

题目链接请戳 这里

 

解题思路

这道题表面上需要你建图,其实只需在bfs扩展节点时“建立”就好了。

用Dijkstra或者SPFA就可求出最短路。

如果单纯地使用隐式图搜索,只能得到最少步数,而题目要求出最少时间。

可以用位运算来改变某一位,速度比较快。比如要设置第二为为1,可以:x | (1 << 2); 要设置第二位为0,可以:x & ~(1 << 2);

同样用位运算,SPFA跑了50ms,而Dijkstra跑了70ms.差距不大,但SPFA不一定比Dijkstra快,因为SPFA不稳定。

从Dijkstra改为SPFA只需把优先队列改为普通队列,并添加一个inq数组,表示节点是否在队列中,因为SPFA的节点是可以重复进入队列的。

最后要说的是,题目要求每一个测试输出换行,即使是最后一个测试。

代码

首先是Dijkstra的

#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
#define N 40
#define M 110
#define INF 1e9
#define MAX 3000000
using namespace std;

typedef pair<int, int> pii;
struct patch {
    int pro_has, pro_no;
    int res_has, res_no;
} patches[M];
int n, m;
int d[MAX], cost[M];
priority_queue<pii, vector<pii>, greater<pii> > q;

int make_bit(int x, int i, bool flag)
{ 
    int temp = 1 << (i - 1);
    return flag ? (x | temp) : (x & ~temp);
}

void init()
{
    for (int i = 0; i < m; i++) {
        patches[i].pro_has = patches[i].res_has = 0;
        patches[i].pro_no = patches[i].res_no = (1 << n) - 1;
    }
}

void read()
{
    char pro[N], res[N];
    init();
    for (int i = 0; i < m; i++) {
        scanf("%d%s%s", &cost[i], pro, res);
        for (int j = 0; j < n; j++) {
            if (pro[j] == '-') patches[i].pro_no = make_bit(patches[i].pro_no, n - j, 0);
            if (pro[j] == '+') patches[i].pro_has = make_bit(patches[i].pro_has, n - j, 1);
            if (res[j] == '-') patches[i].res_no = make_bit(patches[i].res_no, n - j, 0);
            if (res[j] == '+') patches[i].res_has = make_bit(patches[i].res_has, n - j, 1);
        }
    }
}

void Dijkstra()
{
    int all_bits = (1 << n) - 1;
    for (int i = 0; i < 1 << n; i++) d[i] = (i == all_bits ? 0 : INF);
    q.push(make_pair(d[all_bits], all_bits));
    while (!q.empty()) {
        pii u = q.top(); q.pop();
        int x = u.second;
        if(u.first != d[x]) continue;
        for (int i = 0; i < m; i++)
            if ((x | patches[i].pro_has) == x && (x & patches[i].pro_no) == x) {
                int v = (x | patches[i].res_has);
                v = (v & patches[i].res_no);
                if (d[v] > d[x] + cost[i]) {
                    d[v] = d[x] + cost[i];
                    q.push(make_pair(d[v], v));
                }
            }
    }
    if (d[0] == INF) printf("Bugs cannot be fixed.\n");
    else printf("Fastest sequence takes %d seconds.\n", d[0]);
}

int main()
{
    int tests = 0;
    scanf("%d%d", &n, &m);
    while (!(n == 0 && m == 0)) {
        printf("Product %d\n", ++tests);
        read();
        Dijkstra();
        scanf("%d%d", &n, &m);
        /*if (!(n == 0 && m == 0)) */printf("\n");
    }
    return 0;
}

 

然后是SPFA的

#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
#define N 40
#define M 110
#define INF 1e9
#define MAX 3000000
using namespace std;

struct patch {
    int pro_has, pro_no;
    int res_has, res_no;
} patches[M];
int n, m;
int d[MAX], cost[M];
bool inq[MAX];
queue<int> q;

int make_bit(int x, int i, bool flag)
{
    int temp = 1 << (i - 1);
    return flag ? (x | temp) : (x & ~temp);
}

void init()
{
    for (int i = 0; i < m; i++) {
        patches[i].pro_has = patches[i].res_has = 0;
        patches[i].pro_no = patches[i].res_no = (1 << n) - 1;
    }
}

void read()
{
    char pro[N], res[N];
    init();
    for (int i = 0; i < m; i++) {
        scanf("%d%s%s", &cost[i], pro, res);
        for (int j = 0; j < n; j++) {
            if (pro[j] == '-') patches[i].pro_no = make_bit(patches[i].pro_no, n - j, 0);
            if (pro[j] == '+') patches[i].pro_has = make_bit(patches[i].pro_has, n - j, 1);
            if (res[j] == '-') patches[i].res_no = make_bit(patches[i].res_no, n - j, 0);
            if (res[j] == '+') patches[i].res_has = make_bit(patches[i].res_has, n - j, 1);
        }
    }
}

void SPFA()
{
    memset(inq, 0, sizeof(inq));
    int all_bits = (1 << n) - 1;
    for (int i = 0; i < 1 << n; i++) d[i] = (i == all_bits ? 0 : INF);
    q.push(all_bits); inq[all_bits] = true;
    while (!q.empty()) {
        int x = q.front(); q.pop();
        inq[x] = false;
        for (int i = 0; i < m; i++)
            if ((x | patches[i].pro_has) == x && (x & patches[i].pro_no) == x) {
                int v = (x | patches[i].res_has);
                v = (v & patches[i].res_no);
                if (d[v] > d[x] + cost[i]) {
                    d[v] = d[x] + cost[i];
                    if (!inq[v]) { 
                        q.push(v);
                        inq[v] = true;
                    }
                }
            }
    }
    if (d[0] == INF) printf("Bugs cannot be fixed.\n");
    else printf("Fastest sequence takes %d seconds.\n", d[0]);
}

int main()
{
    int tests = 0;
    scanf("%d%d", &n, &m);
    while (!(n == 0 && m == 0)) { 
        printf("Product %d\n", ++tests);
        read();
        SPFA();
        scanf("%d%d", &n, &m);
        /*if (!(n == 0 && m == 0)) */printf("\n");
    }
    return 0;
}

 

posted @ 2016-11-05 19:45  啊嘞  阅读(350)  评论(0编辑  收藏  举报