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倍以上,但是还是好几分钟;

无法满足我们的要求;

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

 

你可能感兴趣的:(ACM)