用二进制表示状态运算起来更快一些,这样一行就可以用一个数字去表示其状态了。按这个思路继续想下去就是如何建图了,其实无论邻接表还是邻接矩阵貌似建完整图的时间复杂度都比较大,而且好多状态未必用的到,因而不如干脆不建完整图,每次都扫描一遍转换规则,如果可以生成另一个状态就将另一个状态直接入队即可。
①判定某些位置是否为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。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 30;
const int MAXM = 110;
const int MAXD = 2000000;
const int INF = 0x3f3f3f3f;
int s[2][MAXM], t[2][MAXM],w[MAXM], N, M;
char a[MAXN], b[MAXN];
int q[MAXD], inq[MAXD], d[MAXD];
int init(){
int i,j;
scanf("%d%d",&N,&M);
if(!N && !M){
return 0;
}
memset(s,0,sizeof(s));
memset(t,0,sizeof(t));
for(i=0;i<M;i++)
{
scanf("%d%s%s",&w[i],a,b);
for(j=0;j<N;j++){
if(a[j]=='+')
s[1][i]+=(1<<j);
if(a[j]!='-')
s[0][i]+=(1<<j);
if(b[j]=='+')
t[1][i]+=(1<<j);
if(b[j]!='-')
t[0][i]+=(1<<j);
}
}
return 1;
}
void SPFA(){
int i,j,k,MAX,front ,rear,u,v;
MAX=1<<N;
for(i=0;i<MAX;i++){
d[i]=INF;
inq[i]=0;
}
front = rear =0;
d[MAX - 1]=0;
q[rear++] = MAX-1;
while(front != rear){
u=q[front ++];
if(front > MAX) front =0;
inq[u]=0;
for(i=0;i<M;i++){
if((u|s[1][i])==u&&(u&s[0][i])==u)
{
v=u;
v|=t[1][i];
v&=t[0][i];
if(d[u]+w[i]<d[v]){
d[v]=d[u]+w[i];
if(!inq[v]){
q[rear++] = v;
if(rear > MAX) rear =0;
inq[v]=1;
}
}
}
}
}
if(d[0]==INF)
printf("Bugs cannot be fixed.\n");
else
printf("Fastest sequence takes %d seconds.\n", d[0]);
}
int main()
{
int T=0;
while(init()){
printf("Product %d\n",++T);
SPFA();
printf("\n");
}
return 0;
}