# Description
Luogu传送门
# Solution
首先看到 ,可以想到状压,然后题目要求我们求从全部为 1 的状态到全部为 0 状态的最短时间,不难想到使用最短路或者 来解决。
对于这道题,我们使用最短路。
把每一种状态当作一个节点,每次处理一个节点时枚举所有的补丁,判断该补丁能否使用,如果可以,直接计算出使用该补丁之后的状态,即为当前点能到达的下一个点。
那么这时还有两个问题:
-
如何判断当前点能否使用。
把每个补丁必须有的 存到 里,必须没有的 存到 里,设当前点状态为 ,那么
(x & b1) = b1 && (x & b2) = 0时,可以转移。 -
如何计算使用补丁之后的状态。
同样把使用补丁之后会消失的 存到 里,会出现的 存到 里,那么由于 都会出现,所以令
x |= f2,会消失的 如何处理呢?也很简单,先令 或上 ,再异或上 。
当然这两个都是小问题了,如果还是不理解的话看代码吧。
(另外本题每组数据后面要输出一行空行)
# Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using namespace std;
namespace IO{
inline int read(){
int x = 0;
char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}
template <typename T> inline void write(T x){
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO;
const int N = 110;
const int inf = 1e9;
int n, m, sta;
struct node{
int t, b1, b2, f1, f2;
}p[N];
char s[N];
int dis[(1 << 21) + 5];
bool vis[(1 << 21) + 5];
inline void spfa(){
memset(dis, 0x3f, sizeof(dis));
queue <int> q;
q.push(sta = (1 << n) - 1), dis[sta] = 0;
while(!q.empty()){
int x = q.front(); q.pop();
vis[x] = 0;
for(int i = 1; i <= m; ++i)
if((x & p[i].b1) == p[i].b1 && !(x & p[i].b2)){
int y = (x | p[i].f1 | p[i].f2) ^ p[i].f1;
if(dis[y] > dis[x] + p[i].t){
dis[y] = dis[x] + p[i].t;
if(!vis[y]) vis[y] = 1, q.push(y);
}
}
}
}
inline void Clear(){
for(int i = 1; i <= m; ++i) p[i] = (node){0, 0, 0, 0, 0};
}
signed main(){
int Case = 0;
while(scanf("%d%d", &n, &m) && n && m){
for(int i = 1; i <= m; ++i){
p[i].t = read();
scanf("%s", s);
for(int j = 0; j < n; ++j){
if(s[j] == '+') p[i].b1 |= (1 << j);
if(s[j] == '-') p[i].b2 |= (1 << j);
}
scanf("%s", s);
for(int j = 0; j < n; ++j){
if(s[j] == '-') p[i].f1 |= (1 << j);
if(s[j] == '+') p[i].f2 |= (1 << j);
}
}
spfa(), Clear();
printf("Product %d\n", ++Case);
if(dis[0] >= inf) printf("Bugs cannot be fixed.\n\n");
else printf("Fastest sequence takes %d seconds.\n\n", dis[0]);
}
return 0;
}