Uva 658 - It's not a Bug, it's a Feature! (最短路)
题目链接 https://vjudge.net/problem/UVA-658
【题意】
补丁在修复bug时,有时也会引入新的bug,假定有n(n<=20)个潜在的bug和m(m<=100)个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug,第一个字符串表示打补丁之前的状态(’+’表示bug必须存在,’-‘表示必须不存在,’0’表示无所谓),第二个字符串表示打补丁之后的状态(’+’表示bug必须存在,’-‘表示必须不存在,’0’表示不变),每个补丁都有一个执行时间,每个补丁可以使用多次,你的任务是用最少的时间把一个所有bug都存在的软件通过打补丁的方式变得没有bug,输出最短时间,无解时输出“Bugs cannot be fixed.”。
【思路】
位运算+最短路,很经典的一道题目,用n为二进制串来表示一种状态,0表示该处没有bug,1表示有,把状态转移所消耗的时间看成路径长度,那么初始状态即一个全1的串,时间为0,要根据现有的m个补丁看看能不能走到二进制串全为0的状态,对dijkstra算法稍作变型即可,每次都枚举所有的补丁,判断当前状态下能否打这个补丁,如果能就进行状态转移,这样只要出现了串为全0的状态说明能把所有bug都消除,否则就无法消除所有bug.
#include<bits/stdc++.h>
using namespace std;
const int maxn = (1 << 20) + 10;
const int maxm = 105;
int n, m, mintime;
bool done[maxn];
struct node {
int time;//耗时(当作路径长度)
int a1, a2, b1, b2;//表示修复前后状态的二进制串
//a1修复前为1,a2修复前为0,b1修复后为1,b2修复后为0
}a[maxm];
struct HeapNode {
int u, d;
HeapNode(int uu, int dd) :u(uu), d(dd) {}
bool operator < (const HeapNode& rhs) const {
return d > rhs.d;
}
};
void init() {
memset(done, 0, sizeof(done));
for (int i = 0; i <= m; ++i) a[i].time = a[i].a1 = a[i].a2 = a[i].b1 = a[i].b2 = 0;
}
bool dijkstra() {
priority_queue<HeapNode> que;
que.push(HeapNode((1 << n) - 1, 0));//初始时的状态,全为1表示bug都存在
while (!que.empty()) {
HeapNode x = que.top();
que.pop();
int u = x.u;
if (u == 0) { mintime = x.d; return true; }
if (done[u]) continue;
done[u] = true;
for (int i = 0; i < m; ++i) {//每次遍历所有的补丁,看能不能往上打
if ((u & a[i].a1) == a[i].a1 && (~u & a[i].a2) == a[i].a2) {//符合要求就打,计算出下一个状态,加入队列
int uu = u | a[i].b1;
uu = uu & ~a[i].b2;
que.push(HeapNode(uu, x.d + a[i].time));
}
}
}
return false;
}
int main() {
int kase = 0;
while (scanf("%d%d", &n, &m) == 2) {
if (!n && !m) break;
init();
for (int i = 0; i < m; ++i) {
int t;
char s1[30], s2[30];
scanf("%d%s%s", &t, s1, s2);
for (int j = 0; j < n; ++j) {
a[i].time = t;
if ('+' == s1[n - 1 - j]) { a[i].a1 = a[i].a1 | (1 << j); }
if ('-' == s1[n - 1 - j]) { a[i].a2 = a[i].a2 | (1 << j); }
if ('+' == s2[n - 1 - j]) { a[i].b1 = a[i].b1 | (1 << j); }
if ('-' == s2[n - 1 - j]) { a[i].b2 = a[i].b2 | (1 << j); }
}
}
/*for (int i = 0; i < m; ++i) {
printf("%d %d %d %d\n", a[i].a1, a[i].a2, a[i].b1, a[i].b2);
}*/
printf("Product %d\n", ++kase);
if (dijkstra()) {
printf("Fastest sequence takes %d seconds.\n", mintime);
}
else {
puts("Bugs cannot be fixed.");
}
putchar('\n');
}
return 0;
}