題意:有n個bug,m個補丁,補丁要在一定條件下才能使用,使用後會發生改變。每個補丁會給出兩個字符串,第一個字符串表示條件,第i位爲0表示對第i個bug沒有要求,+表示必須存在,-表示必須不存在;第二個字符串表示使用後的變化,-表示沒有,+表示有,0表示不變。
就是最短路問題,當一個狀態能使用一個補丁變化到另一個狀態時就是這兩個狀態之間有一條邊,權值就是補丁執行的時間。用二進制數表示狀態,然後對於每個補丁也用二進制來處理,然後求從(1 << n) - 1開始求最短路,到0的最短距離。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int vis[2000000];
int dis[2000000];
const int INF = 0x3f3f3f3f;
struct node{
int d, x;
node(int d, int x):d(d), x(x){}
};
bool operator <(const node &a, const node &b) {
if(a.x != b.x)
return a.x < b.x;
return a.d < b.d;
}
priority_queue<node> q;
char s[105];
int tm[101];
int st[101][4];
int main() {
int n, m, i, j, a, ks = 1;
while(~scanf("%d%d", &n, &m) && n) {
memset(vis, 0, sizeof(vis));
memset(dis, 0x3f, sizeof(dis));
for(i = 0; i < m; i++) {
scanf("%d%s", &tm[i], s);
st[i][0] = st[i][1] = 0;
for(j = 0; j < n; j++) {
st[i][0] <<= 1;
st[i][1] <<= 1;
if(s[j] == '-')
st[i][0] |= 1;
else if(s[j] == '+') st[i][1] |= 1;
}
scanf("%s", s);
st[i][2] = 0;
st[i][3] = 0;
for(j = 0; j < n; j++) {
st[i][2] <<= 1;
st[i][3] <<= 1;
if(s[j] == '+')
st[i][3] |= 1;
if(s[j] != '-')
st[i][2] |= 1;
}
}
while(q.size())
q.pop();
int u = (1 << n) - 1;
dis[u] = 0;
q.push(node(u, 0));
while(q.size()) {
node t = q.top();
q.pop();
for(i = 0; i < m; i++) {
if((t.d & st[i][0]) == 0 && (t.d & st[i][1]) == st[i][1]) {
u = (t.d & st[i][2]) | st[i][3];
if(t.x + tm[i] < dis[u]) {
dis[u] = t.x + tm[i];
q.push(node(u, dis[u]));
}
}
}
}
if(dis[0] == INF)
printf("Product %d\nBugs cannot be fixed.\n\n", ks++);
else
printf("Product %d\nFastest sequence takes %d seconds.\n\n", ks++, dis[0]);
}
return 0;
}
/**
3 3
1 000 00-
1 00- 0-+
2 0-- -++
4 1
7 0-0+ ----
0 0
**/