# Description

Luogu 传送门

# Solution

首先看到 n20n \leq 20,可以想到状压,然后题目要求我们求从全部为 1 的状态到全部为 0 状态的最短时间,不难想到使用最短路或者 dp\text{dp} 来解决。

对于这道题,我们使用最短路。

把每一种状态当作一个节点,每次处理一个节点时枚举所有的补丁,判断该补丁能否使用,如果可以,直接计算出使用该补丁之后的状态,即为当前点能到达的下一个点。

那么这时还有两个问题:

  • 如何判断当前点能否使用。

    把每个补丁必须有的 bug\text{bug} 存到 b1b_1 里,必须没有的 bug\text{bug} 存到 b2b_2 里,设当前点状态为 xx,那么 (x & b1) = b1 && (x & b2) = 0 时,可以转移。

  • 如何计算使用补丁之后的状态。

    同样把使用补丁之后会消失的 bug\text{bug} 存到 f1f_1 里,会出现的 bug\text{bug} 存到 f2f_2 里,那么由于 f2f_2 都会出现,所以令 x |= f2 ,会消失的 bug\text{bug} 如何处理呢?也很简单,先令 xx 或上 f1f_1,再异或上 f1f_1

当然这两个都是小问题了,如果还是不理解的话看代码吧。

(另外本题每组数据后面要输出一行空行)

# Code

#include <bits/stdc++.h>
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;
}