ACM之八数码问题BFS搜索数独游戏的模拟(中)

题目描述;数独游戏的内核模拟
八数码问题;
编号为1到8的8个正方形滑块被摆成3行3列;(有一个格子留空);
每次可以把与空格相邻的滑块(有公共边才算相邻)移到空格中;
而它原来的位置就成为了新的空格;给定初始局面和目标局面(用0表示空格);
你的任务死计算出最少的移动步数;和移动过程;如果无法到达目标局面,则输出-1;

在这节里我们使用c++封装的stl库里面的set类库来帮助我们进行判断是否访问过的操作;

这里用vis.count(s)的返回值来判断s是否在栈里面

用vis.insert(s)将s插入到vis里面;

  1 #include <iostream>
  2 #include <fstream>
  3 #include <set>
  4 using namespace std;
  5 #include <stdio.h>
  6 #include <stdlib.h>
  7 #include <string.h>
  8 #define MAX 1000000
  9 //为什么选择这么大呢?排列数9!;
 10 typedef struct Node
 11 {
 12     int state[9];//存放本状态各个位置的数码值;
 13     int fa;//记录父节点的下标;
 14     int deepth;
 15     int last_x;
 16     int last_y;
 17 
 18 }Node;
 19 Node q[MAX];//构成状态数组;
 20 int i,j,k;
 21 set<int> vis;
 22 void init_lookup_table()
 23 {
 24     vis.clear();
 25 }
 26 int try_to_insert(int s)
 27 {
 28     int v=0;
 29     for(k=0;k<9;k++)
 30     {
 31         v=v*10+q[s].state[k];
 32 
 33     }
 34     if(vis.count(v))return 0;
 35     vis.insert(v);
 36     return 1;
 37 }
 38 const int dx[4]={-1,1,0,0};//左右上下;
 39 const int dy[4]={0,0,-1,1};
 40 int bfs();//广度优先找到目标状态;
 41 void print_path(int founded);//根据fa成员,通过递归技术实现状态依次输出;
 42 Node destination;//存储目标状态;
 43 int main()
 44 {
 45     /*首先输入起始状态和目标状态*/
 46     memset(q,0,sizeof q);
 47     for(i=0;i<9;i++)
 48     {
 49         scanf("%d",&(q[0].state[i]));
 50     }
 51     for(i=0;i<9;i++)
 52     {
 53         scanf("%d",&destination.state[i]);
 54     }
 55     
 56     
 57     /*然后进行搜索并输出*/
 58     int founded=bfs();
 59     if(founded)
 60         print_path(founded);
 61     else
 62         printf("-1\n");
 63     system("pause");
 64     return 0;
 65 }
 66 int bfs()
 67 {
 68 
 69     vis[0].visited=1;//第一个结点访问;
 70     vis_cur++;*/
 71     init_lookup_table();
 72     try_to_insert(0);
 73     int front=0,rear=1;//用来模拟队列的先进先出,达到广度优先的目的;
 74     while (front<rear)
 75     {
 76         Node &first=q[front];
 77         if (memcmp(first.state,destination.state,sizeof destination.state)==0)
 78         {//找到了目标状态;
 79             return front;
 80         }
 81         for(i=0;i<9;i++)
 82             if (!first.state[i])
 83             {//找到空格处;
 84                 break;
 85             }
 86 
 87         for(j=0;j<4;j++)
 88         {//向四个方向进行转换;
 89             Node &new_Node=q[rear];
 90             memcpy(new_Node.state,first.state,sizeof first.state);
 91             int new_x=i%3+1+dx[j];
 92             int new_y=i/3+1+dy[j];
 93             
 94             if (new_x>0&&new_y>0&&new_x<4&&new_y<4)
 95             {
 96                 //位置合法
 97                 new_Node.state[i]=new_Node.state[i+dx[j]+3*dy[j]];//空格位置;
 98                 new_Node.state[i+dx[j]+3*dy[j]]=0;//新的状态形成了;
 99                     new_Node.fa=front;
112                     new_Node.deepth=first.deepth+1;
113                     new_Node.last_x=dx[j];
114                     new_Node.last_y=dy[j];
115                     if(try_to_insert(rear))
119                     rear++;
120                            
122             }//if
123         }//for
124         front++;
125        
126   }//while 127 return 0; 128 } 129 void print_path(int founded) 130 { 131 if(q[founded].fa!=founded) 132 { 133 print_path(q[founded].fa); 134 } 135 for(i=0;i<3;i++) 136 { 137 for(j=0;j<3;j++) 138 { 139 printf("%d ",q[founded].state[3*i+j]); 140 } 141 printf("\n"); 142 } 143 printf("\n"); 144 }


经过测试发现这个虽然使用stl的类库,把速度提高了8倍以上,但是还是好几分钟;

无法满足我们的要求;

看来要从数据结构上考虑了;下一个博客我们试一下其它的方法;

原文地址:https://www.cnblogs.com/dragonfive/p/2979545.html