八数码第六境界——双向BFS+康托展开判重+回溯记录路径+逆序数判无解

(建议先看前5大境界)

这里相比于上一境界,又增加了一个逆序数判无解的操作,因为第5个境界,双向bfs在无解的时候,显现出了比单向bfs更低的效率(因为他出了更多次的队列,相比于单向 bfs)。


什么是逆序数?

比如2 4 3 1。

依次看下去,2比1大,4比3大,4比1大,3比1大。所以逆序数就是4。

所以我们得知了逆序数就是体现在一个逆字上。相比于在正常序列下1234。有多少前面的数比后面的数大的这种情况,就是逆序数了。


逆序数为什么可以判无解?

因为如果起始状态和目标状态,如果把目标状态的x也放到右下角,如果起始状态逆序数的奇偶性和目标状态的奇偶性是一样的,那行就代表这两个状态可以互相移动到。反之,就不可以互相移动到。


(感兴趣的的人看看证明吧,不感兴趣直接用也行)

http://blog.csdn.net/qq_36523667/article/details/78798403


判断代码

  1. bool inverse(char ss[])  
  2. {  
  3.     int t=0,x,y;  
  4.     for(int i=1;i<9;i++)  
  5.         for(int j=0;j<i;j++)  
  6.         {  
  7.             if(ss[j]=='x')continue;  
  8.             else x=ss[j]-'0';  
  9.             if(ss[i]=='x')continue;  
  10.             else y=ss[i]-'0';  
  11.             if(x>y)  
  12.                 t++;  
  13.         }  
  14.     if(t&1)  
  15.         return true;  
  16.     return false;  
  17. }  
这里x就可以直接忽略了,因为他指代的是9,没影响的。

这个判断代码另外的步骤我就不是很懂了,不是应该遍历每一个数,在遍历的过程中,找剩下的数比他小的吗?

所以这里读者看不懂可以按照自己的思路来写。(此外我发现他的代码并没有把x归到右下角再进行逆序数的查找!这个应该是要的!)


全部代码(除了判断代码,都和上一章一样)

  1. #define N 512345  
  2.   
  3. char ss[10];  
  4. struct node  
  5. {  
  6.     char str[10];  
  7.     int mark,num;  
  8.     int index,hashnum;  
  9. };  
  10. struct res  
  11. {  
  12.     int fa,now;  
  13. }res1[N],res2[N];  
  14. int vis1[N],vis2[N];  
  15. int  fac[] = {1,1,2,6,24,120,720,5040,40320};  
  16. int over,ans1,ans2,sum1,sum2,cnt1,cnt2;  
  17. int hehe[N];  
  18. int KT(char ss[])  
  19. {  
  20.     int i, j, t, sum;  
  21.     int s[10];  
  22.     for(i=0;i<9;i++)  
  23.     {  
  24.         if(ss[i]=='x')  
  25.             s[i]=0;  
  26.         else  
  27.             s[i]=ss[i]-'0';  
  28.     }  
  29.     sum = 0;  
  30.     for (i=0; i<9; i++)  
  31.     {  
  32.         t = 0;  
  33.         for (j=i+1; j<9; j++)  
  34.             if (s[j] < s[i])  
  35.                 t++;  
  36.         sum += t*fac[9-i-1];  
  37.     }  
  38.     return sum+1;  
  39. }  
  40. bool bfs(char ss[], int temp)  
  41. {  
  42.     char c;  
  43.     queue<node> q;  
  44.     while(!q.empty())q.pop();  
  45.   
  46.     node g,h;  
  47.     for(int i=0;i<8;i++)  
  48.         g.str[i]=i+1+'0';  
  49.     g.str[8]='x';g.str[9]='\0';  
  50.     g.mark=0;g.num=0;g.index=8;  
  51.     vis1[KT(g.str)]=0;  
  52.     q.push(g);  
  53.     for(int i=0;i<9;i++)  
  54.         g.str[i]=ss[i];  
  55.     g.mark=1;g.num=0;g.index=temp;  
  56.     vis2[KT(g.str)]=0;  
  57.     q.push(g);  
  58.     sum1=sum2=1;  
  59.     cnt1=cnt2=1;  
  60.   
  61.     while(!q.empty())  
  62.     {  
  63.         g=q.front();q.pop();  
  64.         int t = KT(g.str);  
  65.         if(g.mark==0)sum1--;  
  66.         else sum2--;  
  67.         if(g.mark==0&&vis2[t]!=-1)  
  68.         {  
  69.             ans1=g.num;  
  70.             ans2=vis2[t];  
  71.             return true;  
  72.         }  
  73.         if(g.mark==1&&vis1[t]!=-1)  
  74.         {  
  75.             ans2=g.num;  
  76.             ans1=vis1[t];  
  77.             return true;  
  78.         }  
  79.         h=g;  
  80.         if((h.index+1)%3!=0)  
  81.         {  
  82.             c=h.str[h.index];h.str[h.index]=h.str[h.index+1];h.str[h.index+1]=c;  
  83.             h.index++;  
  84.             if(!h.mark){res1[cnt1].now=4;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}  
  85.             else {res2[cnt2].now=4;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}  
  86.             int t=KT(h.str);  
  87.             if(vis1[t]==-1&&!h.mark)  
  88.             {  
  89.                 vis1[t]=h.num;  
  90.                 q.push(h);  
  91.                 sum1++;  
  92.             }  
  93.             else if(vis2[t]==-1&&h.mark)  
  94.             {  
  95.                 vis2[t]=h.num;  
  96.                 q.push(h);  
  97.                 sum2++;  
  98.             }  
  99.         }  
  100.         h=g;  
  101.         if(h.index%3!=0)  
  102.         {  
  103.             c=h.str[h.index];h.str[h.index]=h.str[h.index-1];h.str[h.index-1]=c;  
  104.             h.index--;  
  105.             if(!h.mark){res1[cnt1].now=3;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}  
  106.             else {res2[cnt2].now=3;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}  
  107.             int t=KT(h.str);  
  108.             if(vis1[t]==-1&&!h.mark)  
  109.             {  
  110.                 vis1[t]=h.num;  
  111.                 q.push(h);  
  112.                 sum1++;  
  113.             }  
  114.             else if(vis2[t]==-1&&h.mark)  
  115.             {  
  116.                 vis2[t]=h.num;  
  117.                 q.push(h);  
  118.                 sum2++;  
  119.             }  
  120.         }  
  121.         h=g;  
  122.         if(h.index<6)  
  123.         {  
  124.             c=h.str[h.index];h.str[h.index]=h.str[h.index+3];h.str[h.index+3]=c;  
  125.             h.index+=3;  
  126.             if(!h.mark){res1[cnt1].now=2;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}  
  127.             else {res2[cnt2].now=2;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}  
  128.             int t=KT(h.str);  
  129.             if(vis1[t]==-1&&!h.mark)  
  130.             {  
  131.                 vis1[t]=h.num;  
  132.                 q.push(h);  
  133.                 sum1++;  
  134.             }  
  135.             else if(vis2[t]==-1&&h.mark)  
  136.             {  
  137.                 vis2[t]=h.num;  
  138.                 q.push(h);  
  139.                 sum2++;  
  140.             }  
  141.         }  
  142.         h=g;  
  143.         if(h.index>2)  
  144.         {  
  145.             c=h.str[h.index];h.str[h.index]=h.str[h.index-3];h.str[h.index-3]=c;  
  146.             h.index-=3;  
  147.             if(!h.mark){res1[cnt1].now=1;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}  
  148.             else {res2[cnt2].now=1;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}  
  149.             int t=KT(h.str);  
  150.             if(vis1[t]==-1&&!h.mark)  
  151.             {  
  152.                 vis1[t]=h.num;  
  153.                 q.push(h);  
  154.                 sum1++;  
  155.             }  
  156.             else if(vis2[t]==-1&&h.mark)  
  157.             {  
  158.                 vis2[t]=h.num;  
  159.                 q.push(h);  
  160.                 sum2++;  
  161.             }  
  162.         }  
  163.         if(sum1==0||sum2==0)  
  164.             return false;  
  165.     }  
  166.     return false;  
  167. }  
  168. bool inverse(char ss[])  
  169. {  
  170.     int t=0,x,y;  
  171.     for(int i=1;i<9;i++)  
  172.         for(int j=0;j<i;j++)  
  173.         {  
  174.             if(ss[j]=='x')continue;  
  175.             else x=ss[j]-'0';  
  176.             if(ss[i]=='x')continue;  
  177.             else y=ss[i]-'0';  
  178.             if(x>y)  
  179.                 t++;  
  180.         }  
  181.     if(t&1)  
  182.         return true;  
  183.     return false;  
  184. }  
  185. int main()  
  186. {  
  187.     int i,j,k,kk,t,x,y,z;  
  188.     while(scanf("%s",ss)!=EOF)  
  189.     {  
  190.         if(ss[0]=='x')x=0;  
  191.         for(i=1;i<9;i++)  
  192.         {  
  193.             scanf("%s",ss+i);  
  194.             if(ss[i]=='x') x=i;  
  195.         }  
  196.   
  197.         if(inverse(ss))  
  198.         {  
  199.             printf("unsolvable\n");  
  200.             continue;  
  201.         }  
  202.   
  203.         ans1=ans2=-1;  
  204.         memset(vis1,-1,sizeof(vis1));  
  205.         memset(vis2,-1,sizeof(vis2));  
  206.         res1[0].now=res2[0].now=-1;  
  207.   
  208.         if(bfs(ss,x))  
  209.         {  
  210.             x=0;  
  211.             if(res2[ans2].now==-1&&res1[ans1].now==-1)  
  212.             {  
  213.                 printf("lr\n");  
  214.                 continue;  
  215.             }  
  216.             while(res2[ans2].now!=-1)  
  217.             {  
  218.                 hehe[x++]=res2[ans2].now;  
  219.                 ans2=res2[ans2].fa;  
  220.             }  
  221.             for(i=x-1;i>=0;i--)  
  222.             {  
  223.                 if(hehe[i]==1)printf("u");  
  224.                 if(hehe[i]==2)printf("d");  
  225.                 if(hehe[i]==3)printf("l");  
  226.                 if(hehe[i]==4)printf("r");  
  227.             }  
  228.             while(res1[ans1].now!=-1)  
  229.             {  
  230.                 if(res1[ans1].now==1)printf("d");  
  231.                 if(res1[ans1].now==2)printf("u");  
  232.                 if(res1[ans1].now==3)printf("r");  
  233.                 if(res1[ans1].now==4)printf("l");  
  234.                 ans1=res1[ans1].fa;  
  235.             }  
  236.         }  
  237.         else  
  238.             printf("unsolvable");  
  239.         printf("\n");  
  240.     }  
  241.     return 0;  
  242. }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值