位运算+最短路
不建图:结点数很多,多达2^n个,并且很多状态碰不到,所以不需要先把图存好,每次取出一个结点,直接枚举m个补丁,看是否能够打得上。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <string>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int N=(1<<20)+5;
int n,m,vis[N],dis[N];
struct node
{
int w;
string s1,s2;
}a[105];
int f(int s,int k)
{
for(int i=0;i<n;i++)
{
int x=(s>>i)&1;
if(x==0&&a[k].s1[n-1-i]=='+')
return 0;
if(x==1&&a[k].s1[n-1-i]=='-')
return 0;
}
return 1;
}
int g(int s,int k)
{
int res=0;
for(int i=n-1;i>=0;i--)
{
int x=(s>>i)&1;
if(a[k].s2[n-1-i]=='0'&&x==1)
res=res*2+1;
else if(a[k].s2[n-1-i]=='+')
res=res*2+1;
else
res*=2;
}
return res;
}
void spfa()
{
int s=(1<<n)-1;
vis[s]=1;
dis[s]=0;
queue<int> q;
q.push(s);
while(!q.empty())
{
int t=q.front();
q.pop();
vis[t]=0;
for(int i=0;i<m;i++)
{
if(f(t,i))
{
int v=g(t,i),w=a[i].w;
if(dis[v]>dis[t]+w)
{
dis[v]=dis[t]+w;
if(vis[v])
continue;
vis[v]=1;
q.push(v);
}
}
}
}
}
int main()
{
int num=1;
while(cin >> n >> m,n||m)
{
memset(dis,inf,sizeof(dis));
memset(vis,0,sizeof(vis));
for(int i=0;i<m;i++)
cin >> a[i].w >> a[i].s1 >> a[i].s2;
spfa();
printf("Product %d\n",num++);
if(dis[0]==inf)
printf("Bugs cannot be fixed.\n");
else
printf("Fastest sequence takes %d seconds.\n",dis[0]);
printf("\n");
}
return 0;
}