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

来源:互联网 发布:jdk 6u linux x64.bin 编辑:程序博客网 时间:2024/05/07 10:25

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

------------------------------------------------------------------------------

接前面两个博客,在这个博客里,我们尝试改变我们使用的判重的数据结构;在第一个博客里我们用的是

数组,也就是顺序结构,速度非常的慢,在第二个博客里我们使用是c++里的set类库,其结构是一种特殊的红黑树

同时使用,整数来存储状态,加快了速度,体现了选择正确的数据结构的重要性,在本博客里,展示的是使用哈希技术实现的随机访问;

随机访问,也就是下标访问法;速度很快;

#include <iostream>#include <fstream>using namespace std;#include <stdio.h>#include <stdlib.h>#include <string.h>//因为这里要用到memcmp和memcpy函数;//这两个函数比我们写的循环效率要高;#define MAX 1000000//为什么选择这么大呢?排列数9!;typedef struct Node{int state[9];//存放本状态各个位置的数码值;int fa;//记录父节点的下标;int deepth;int last_x;int last_y;}Node;Node q[MAX];//构成状态数组;int head[MAX];int hash_next[MAX];const int dx[4]={-1,1,0,0};//左右上下;const int dy[4]={0,0,-1,1};int bfs();//广度优先找到目标状态;void print_path(int founded);//根据fa成员,通过递归技术实现状态依次输出;Node destination;//存储目标状态;int i,j,k;int main(){/*首先输入起始状态和目标状态;*/memset(q,0,sizeof q);for(i=0;i<9;i++){scanf("%d",&(q[0].state[i]));}for(i=0;i<9;i++){scanf("%d",&destination.state[i]);}memset(head,0,sizeof head);memset(hash_next,0,sizeof hash_next);/*然后进行搜索并输出;*/int founded=bfs();if(founded){printf("%d\n",q[founded].deepth);print_path(founded);}elseprintf("-1\n");system("pause");return 0;}int bfs(){int front=1,rear=2;//用来模拟队列的先进先出,达到广度优先的目的;int v=0;q[1].deepth=0;q[1].fa=1;for(k=0;k<9;k++){v=10*v+q[front].state[k];}v=v%MAX;head[v]=1;while (front<rear){Node &first=q[front];if (memcmp(first.state,destination.state,sizeof destination.state)==0){//找到了目标状态;return front;}for(i=0;i<9;i++)if (!first.state[i]){//找到空格处;break;}for(j=0;j<4;j++){//向四个方向进行转换;Node &new_Node=q[rear];memcpy(new_Node.state,first.state,sizeof first.state);int new_x=i%3+1+dx[j];int new_y=i/3+1+dy[j];if (new_x>0&&new_y>0&&new_x<4&&new_y<4){//位置合法;new_Node.state[i]=new_Node.state[i+dx[j]+3*dy[j]];//空格位置;new_Node.state[i+dx[j]+3*dy[j]]=0;//新的状态形成了;v=0;for(k=0;k<9;k++)//这里不用i,j因为i,j是全局变量且本函数是在循环里面的;{v=10*v+new_Node.state[k];}v=v%MAX;int u=head[v];int found=0;while(u){if(memcmp(q[u].state,new_Node.state,sizeof new_Node.state)==0){found=1;break;}u=hash_next[u];}if(!found)//没有被访问;{new_Node.fa=front;new_Node.deepth=first.deepth+1;new_Node.last_x=dx[j];new_Node.last_y=dy[j];hash_next[rear]=head[v];head[v]=rear;rear++;}//if}//if}//forfront++;//printf("%d %d\n",front,q[front].deepth);}//whilereturn 0;}void print_path(int founded){if(q[founded].fa!=founded){print_path(q[founded].fa);}for(i=0;i<3;i++){for(j=0;j<3;j++){printf("%d ",q[founded].state[3*i+j]);}printf("\n");}printf("\n");}

这里使用了哈希技术,把状态进行操作,使其作为下标;这样就能不受数组大小的限制,马上访问到对应的状态;

哈希表的执行效率高,适用的范围很广,可以快速的查找;