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; }