本题有两大难点,一是建图。其实无论邻接表还是邻接矩阵貌似建完整图的时间复杂度都比较大,而且好多状态未必用的到,因而不如干脆不建完整图,每次都扫描一遍转换规则,如果可以生成另一个状态就将另一个状态直接入队即可。状态可以用二进制表示。
二是判断当前状态,用二进制来判断。
①判定某些位置是否为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。
// Created by Chenhongwei in 2015.
// Copyright (c) 2015 Chenhongwei. All rights reserved.
#include "iostream"
#include "cstdio"
#include "cstdlib"
#include "cstring"
#include "climits"
#include "queue"
#include "cmath"
#include "map"
#include "set"
#include "stack"
#include "vector"
#include "sstream"
#include "algorithm"
using namespace std;
const int inf=1e9;
const int maxn=(2<<20)+100;
typedef long long ll;
bool vis[maxn];
int d[maxn];
int b[2][150],a[2][150];
int n,m;
int w[150];
void SPFA()
{
memset(vis,0,sizeof vis);
memset(d,0x3f,sizeof d);
int inti=(1<<n)-1;
queue<int >q;
q.push(inti);
d[inti]=0;
vis[inti]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
// cout<<u<<endl;
vis[u]=0;
for(int i=1;i<=m;i++)
if((u&b[1][i])==u&&(u|b[0][i])==u)
{
int v=u;
v|=a[0][i];
v&=a[1][i];
if(d[v]>d[u]+w[i])
{
d[v]=d[u]+w[i];
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
if(d[0]>inf)
cout<<"Bugs cannot be fixed."<<endl<<endl;
else
cout<<"Fastest sequence takes "<<d[0]<<" seconds."<<endl<<endl;
}
int main()
{
//ios::sync_with_stdio(false);
// freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int kase=0;
while(scanf("%d%d",&n,&m)&&(n+m))
{
printf("Product %d\n",++kase);
char s[150],t[150];
memset(a,0,sizeof a);
memset(b,0,sizeof b);
for(int i=1;i<=m;i++)
{
scanf("%d%s%s",&w[i],s,t);
for(int j=0;j<n;j++)
{
if(s[j]=='+')
b[0][i]+=(1<<j);
if(s[j]!='-')
b[1][i]+=(1<<j);
if(t[j]=='+')
a[0][i]+=(1<<j);
if(t[j]!='-')
a[1][i]+=(1<<j);
}
// cout<<b[0][i]<<' '<<b[1][i]<<' '<<a[0][i]<<' '<<a[1][i]<<endl;
}
SPFA();
}
return 0;
}