(请先看前4大境界)
这里较上一境界,就是把反向的BFS,弄成了双向的BFS。先不说算法的优劣,就光这个双向的BFS,就是指的记录和学习的。
很简单,在结合之前所学的基础上,把单向扩展成双向即可。
结构体
- struct node
- {
- char str[10];
- int mark,num;
- int index,hashnum;
- };
回溯路径结构体数组,就需要多开一个
- struct res
- {
- int fa,now;
- }res1[N],res2[N];
访问与否,也需要多开一个
- int vis1[N],vis2[N];
先让终点状态入队列
- g.mark=0;g.num=0;g.index=8;
- vis1[KT(g.str)]=0;
- q.push(g);
再让起点状态入队列
- for(int i=0;i<9;i++)
- g.str[i]=ss[i];
- g.mark=1;g.num=0;g.index=temp;
- vis2[KT(g.str)]=0;
- q.push(g);
所以这里我们得知了,我们虽然是bfs,但是仍旧共享一个队列,我们一开始,也是将两个开始状态都入队。
如果找到,应该进行的判断
- if(g.mark==0&&vis2[t]!=-1)
- {
- ans1=g.num;
- ans2=vis2[t];
- return true;
- }
- if(g.mark==1&&vis1[t]!=-1)
- {
- ans2=g.num;
- ans1=vis1[t];
- return true;
- }
bfs流程
- h=g;
- if((h.index+1)%3!=0)
- {
- c=h.str[h.index];h.str[h.index]=h.str[h.index+1];h.str[h.index+1]=c;
- h.index++;
- if(!h.mark){res1[cnt1].now=4;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}
- else {res2[cnt2].now=4;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}
- int t=KT(h.str);
- if(vis1[t]==-1&&!h.mark)
- {
- vis1[t]=h.num;
- q.push(h);
- sum1++;
- }
- else if(vis2[t]==-1&&h.mark)
- {
- vis2[t]=h.num;
- q.push(h);
- sum2++;
- }
- }
c=h.str[h.index];h.str[h.index]=h.str[h.index+1];h.str[h.index+1]=c; 这个就是右移操作
h.index++; 指代h状态中x所在的位置
接下来的那个if,!h.mark,那意思就是为0的情况,那就是从终点开始的bfs。
if里面的内容就是用来回溯路径的。
else就是代表从起点开始的bfs。
这个时候h较g已经发生了改变,再通过康托展开取得值。
接下来的if。如果这个状态再vis1中未曾出现过且现在是起点开始的bfs,那就把这个状态置为已访问,再把这个新的状态入队列。
最后的sum1++就耐人寻味了。
我们先找到sum所在的地方
声明处
sum1=sum2=1;
- while(!q.empty())
- {
- g=q.front();q.pop();
- int t = KT(g.str);
- if(g.mark==0)sum1--;
- else sum2--;
-
最后的终止条件
- if(sum1==0||sum2==0)
- return false;
如果其中一个的元素出光了,那就代表返回false,退出了。为什么其中一个元素出光了就代表没机会了呢?难道不能之后从另一个点出发的bfs又走回到你这个路径上来了呢?其实我想说,仅仅这样还限定的不严格。不过我们就先谈谈这个。我们先假设,其中一个bfs所有情况遍历了,另一个bfs在随后走到了这条路上来。那么我想问,这是否意味着另一个bfs总有办法走到之前的bfs的路上来,也就证明他们是相通的。但是第一个bfs走光了,那肯定也代表他把能走相通的路都走过了!所以这是矛盾的。具体什么时候才是真正的没机会了呢?不必深究了。
全部代码
- #define N 512345
- char ss[10];
- struct node
- {
- char str[10];
- int mark,num;
- int index,hashnum;
- };
- struct res
- {
- int fa,now;
- }res1[N],res2[N];
- int vis1[N],vis2[N];
- int fac[] = {1,1,2,6,24,120,720,5040,40320};
- int over,ans1,ans2,sum1,sum2,cnt1,cnt2;
- int hehe[N];
- int KT(char ss[])
- {
- int i, j, t, sum;
- int s[10];
- for(i=0;i<9;i++)
- {
- if(ss[i]=='x')
- s[i]=0;
- else
- s[i]=ss[i]-'0';
- }
- sum = 0;
- for (i=0; i<9; i++)
- {
- t = 0;
- for (j=i+1; j<9; j++)
- if (s[j] < s[i])
- t++;
- sum += t*fac[9-i-1];
- }
- return sum+1;
- }
- bool bfs(char ss[], int temp)
- {
- char c;
- queue<node> q;
- while(!q.empty())q.pop();
- node g,h;
- for(int i=0;i<8;i++)
- g.str[i]=i+1+'0';
- g.str[8]='x';g.str[9]='\0';
- g.mark=0;g.num=0;g.index=8;
- vis1[KT(g.str)]=0;
- q.push(g);
- for(int i=0;i<9;i++)
- g.str[i]=ss[i];
- g.mark=1;g.num=0;g.index=temp;
- vis2[KT(g.str)]=0;
- q.push(g);
- sum1=sum2=1;
- cnt1=cnt2=1;
- while(!q.empty())
- {
- g=q.front();q.pop();
- int t = KT(g.str);
- if(g.mark==0)sum1--;
- else sum2--;
- if(g.mark==0&&vis2[t]!=-1)
- {
- ans1=g.num;
- ans2=vis2[t];
- return true;
- }
- if(g.mark==1&&vis1[t]!=-1)
- {
- ans2=g.num;
- ans1=vis1[t];
- return true;
- }
- h=g;
- if((h.index+1)%3!=0)
- {
- c=h.str[h.index];h.str[h.index]=h.str[h.index+1];h.str[h.index+1]=c;
- h.index++;
- if(!h.mark){res1[cnt1].now=4;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}
- else {res2[cnt2].now=4;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}
- int t=KT(h.str);
- if(vis1[t]==-1&&!h.mark)
- {
- vis1[t]=h.num;
- q.push(h);
- sum1++;
- }
- else if(vis2[t]==-1&&h.mark)
- {
- vis2[t]=h.num;
- q.push(h);
- sum2++;
- }
- }
- h=g;
- if(h.index%3!=0)
- {
- c=h.str[h.index];h.str[h.index]=h.str[h.index-1];h.str[h.index-1]=c;
- h.index--;
- if(!h.mark){res1[cnt1].now=3;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}
- else {res2[cnt2].now=3;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}
- int t=KT(h.str);
- if(vis1[t]==-1&&!h.mark)
- {
- vis1[t]=h.num;
- q.push(h);
- sum1++;
- }
- else if(vis2[t]==-1&&h.mark)
- {
- vis2[t]=h.num;
- q.push(h);
- sum2++;
- }
- }
- h=g;
- if(h.index<6)
- {
- c=h.str[h.index];h.str[h.index]=h.str[h.index+3];h.str[h.index+3]=c;
- h.index+=3;
- if(!h.mark){res1[cnt1].now=2;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}
- else {res2[cnt2].now=2;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}
- int t=KT(h.str);
- if(vis1[t]==-1&&!h.mark)
- {
- vis1[t]=h.num;
- q.push(h);
- sum1++;
- }
- else if(vis2[t]==-1&&h.mark)
- {
- vis2[t]=h.num;
- q.push(h);
- sum2++;
- }
- }
- h=g;
- if(h.index>2)
- {
- c=h.str[h.index];h.str[h.index]=h.str[h.index-3];h.str[h.index-3]=c;
- h.index-=3;
- if(!h.mark){res1[cnt1].now=1;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}
- else {res2[cnt2].now=1;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}
- int t=KT(h.str);
- if(vis1[t]==-1&&!h.mark)
- {
- vis1[t]=h.num;
- q.push(h);
- sum1++;
- }
- else if(vis2[t]==-1&&h.mark)
- {
- vis2[t]=h.num;
- q.push(h);
- sum2++;
- }
- }
- if(sum1==0||sum2==0)
- return false;
- }
- return false;
- }
- int main()
- {
- int i,j,k,kk,t,x,y,z;
- while(scanf("%s",ss)!=EOF)
- {
- if(ss[0]=='x')x=0;
- for(i=1;i<9;i++)
- {
- scanf("%s",ss+i);
- if(ss[i]=='x') x=i;
- }
- ans1=ans2=-1;
- memset(vis1,-1,sizeof(vis1));
- memset(vis2,-1,sizeof(vis2));
- res1[0].now=res2[0].now=-1;
- if(bfs(ss,x))
- {
- x=0;
- if(res2[ans2].now==-1&&res1[ans1].now==-1)
- {
- printf("lr\n");
- continue;
- }
- while(res2[ans2].now!=-1)
- {
- hehe[x++]=res2[ans2].now;
- ans2=res2[ans2].fa;
- }
- for(i=x-1;i>=0;i--)
- {
- if(hehe[i]==1)printf("u");
- if(hehe[i]==2)printf("d");
- if(hehe[i]==3)printf("l");
- if(hehe[i]==4)printf("r");
- }
- while(res1[ans1].now!=-1)
- {
- if(res1[ans1].now==1)printf("d");
- if(res1[ans1].now==2)printf("u");
- if(res1[ans1].now==3)printf("r");
- if(res1[ans1].now==4)printf("l");
- ans1=res1[ans1].fa;
- }
- }
- else
- printf("unsolvable");
- printf("\n");
- }
- return 0;
- }