/**
* 我真服了。 UVa 数组越界只返回WA,不给RE 这题debug了两天,WA了两天
* 最后发现就是数组越界的问题!!
* 做这题学了个很不错的位运算技巧:
* 这样写下来时间还是比较多,后来看了别人的解题报告,发现在判定当前状态是否可以转换的时候可以直接用位运算去操作:
①判定某些位置是否为1,如判定2、4位置为1,则转化为判断x|0101是否等于x。
②判定某些位置是否为0,如判定2、4位置为0,则转化为判断x&1010是否等于x。
③将某些位置转化为1,如2、4位置转化为1,则令x=x|0101。
④将某些位置转化为0,如2、4位置转化为0,则令x=x&1010。
* 摘自 http://www.cnblogs.com/staginner/archive/2011/10/25/2223489.html
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#define DEBUG 0
#define INF 0x3fffffff
#define MAXS 25
#define MAXM 105
typedef long long LL;
using namespace std;
int n, m;
int dis[1 << MAXS], vis[1 << MAXS], posi1[MAXM], negt1[MAXM], posi2[MAXM], negt2[MAXM], times[MAXM];
queue<int> q;
struct Node {
int v, t;
Node() {}
Node(int vv, int tt) {v = vv; t = tt;}
bool operator < (const Node &a) const {
return t > a.t;
}
};
priority_queue<Node> pq;
void init() {
while(!q.empty()) q.pop();
for(int i = 0; i < MAXM; i ++)
posi1[i] = posi2[i] = negt1[i] = negt2[i] = 0;
int len = 1 << n;
for(int i = 0; i < len; i ++) {
dis[i] = INF;
vis[i] = 0;
}
}
void change(char *str1, char *str2, int x) {
for(int i = 0; str1[i]; i ++) {
if(str1[i] == '+')
posi1[x] |= (1 << i);
if(str1[i] != '-')
negt1[x] |= (1 << i);
}
for(int i = 0; str2[i]; i ++) {
if(str2[i] == '+')
posi2[x] |= (1 << i);
if(str2[i] != '-')
negt2[x] |= (1 << i);
}
}
void dijkstra() {
while(!pq.empty()) pq.pop();
int start = (1 << n) - 1;
pq.push(Node(start, 0));
dis[start] = 0;
if(DEBUG)
printf("start: %d\n", start);
while(!pq.empty()) {
Node cur = pq.top(); pq.pop();
if(DEBUG) printf("cur: %d\n", cur.v);
if(vis[cur.v]) continue;
vis[cur.v] = 1;
if(cur.v == 0) {
break;
}
for(int i = 0; i < m; i ++) {
int next = cur.v;
if((cur.v | posi1[i]) == cur.v && (cur.v & negt1[i]) == cur.v) {
next |= posi2[i];
next &= negt2[i];
if(dis[next] > dis[cur.v] + times[i]) {
dis[next] = dis[cur.v] + times[i];
pq.push(Node(next, dis[next]));
if(DEBUG)
printf("patch: %d dis[%d]: %d\n", i, next, dis[next]);
}
}
}
}
if(dis[0] == INF) printf("Bugs cannot be fixed.\n\n");
else printf("Fastest sequence takes %d seconds.\n\n", dis[0]);
}
int main()
{
int product = 1;
while(scanf("%d%d", &n, &m), n + m) {
printf("Product %d\n", product ++);
init();
char str1[MAXS], str2[MAXS];
for(int i = 0; i < m; i ++) {
scanf("%d%s%s", ×[i], str1, str2);
change(str1, str2, i);
}
dijkstra();
}
return 0;
}
UVa 658 It's not a Bug, it's a Feature! 位运算技巧+dijkstra优先队列优化
最新推荐文章于 2017-04-27 21:11:31 发布