考虑到状态数较多,我们不选择存点,而是每次检测可行的变化方式(即边)来前进。考虑到所有的bug都只有存在和不存在两种情况所以选择使用二进制进行保存。
AC代码:
#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
typedef long long ll;
struct MOVE{
string in,out;
ll w;
friend bool operator<(MOVE a,MOVE b){
return a.w<b.w;
}
}mov[105];
struct node{
int id;ll w;
node(int id=0,ll w=0):id(id),w(w){}
friend bool operator<(node a,node b){
return a.w>b.w;
}
};
int n,m;
priority_queue<node> q;
ll dis[1<<21];int vis[1<<21];
bool check(int id,string in)
{
for(int i=0;i<n;i++)
{
if(in[i]=='-'){
if(((id>>i)&1)) return false;
}else if(in[i]=='+'){
if(!((id>>i)&1)) return false;
}else{
continue;
}
}
return true;
}
int change(int id,string out)
{
for(int i=0;i<n;i++){
if(out[i]=='-'){
id=(~((~id)|(1<<i)));
}
else if(out[i]=='+'){
id|=(1<<i);
}
}
return id;
}
void Dijkstra()
{
int beg=0;
for(int i=0;i<n;i++) beg|=(1<<i);
for(int i=0;i<(1<<21);i++) dis[i]=inf;
memset(vis,0,sizeof(vis));
while(!q.empty()) q.pop();
q.push(node(beg,0)),dis[beg]=0;
while(!q.empty())
{
node s=q.top();
q.pop();
int id=s.id;
if(vis[id]) continue;
vis[id]=1;
if(dis[id]!=s.w) continue;
for(int i=1;i<=m;i++)
{
if(check(s.id,mov[i].in))
{
int nxtid=change(s.id,mov[i].out);
if(dis[nxtid]>dis[s.id]+mov[i].w)
{
dis[nxtid]=dis[s.id]+mov[i].w;
q.push(node(nxtid,dis[nxtid]));
}
}
}
}
}
int main()
{
int tot=0;
while(~scanf("%d%d",&n,&m)&&(n&&m))
{
for(int i=1;i<=m;i++)
{
cin>>mov[i].w>>mov[i].in>>mov[i].out;
}
Dijkstra();
int obj=0;
//if(tot) printf("\n");
printf("Product %d\n",++tot);
if(dis[obj]==inf) printf("Bugs cannot be fixed.\n");
else printf("Fastest sequence takes %lld seconds.\n",dis[obj]);
cout<<endl;
}
}