题目描述
Description
Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入描述
Input Description
输入初试状态,一行九个数字,空格用0表示
输出描述
Output Description
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
样例输入
Sample Input
283104765
样例输出
Sample Output
4
数据范围及提示
Data Size & Hint
详见试题
1 #include<iostream> 2 #include<cstdio> 3 #define N 500000 4 using namespace std; 5 int step[N]; 6 struct node{ 7 int map[4][4]; 8 }a[N]; 9 int yd[4] = {0,0,1,-1}; 10 int yyd[4] = {1,-1,0,0}; 11 int g[4][4]={{0,0,0,0},{0,1,2,3},{0,8,0,4},{0,7,6,5}}; 12 int ha[3733800]; 13 int h=0; 14 int t=1; 15 int flag; 16 bool pd(int x,int y)//判断不越界 17 { 18 if(x>=1&&x<=3&&y>=1&&y<=3) 19 return 1; 20 return 0; 21 } 22 bool bj()//将移动后的新矩阵与目标矩阵进行对比 23 { 24 for(int i=1;i<=3;i++) 25 for(int j=1;j<=3;j++) 26 if(a[t].map[i][j]!=g[i][j]) 27 return 0; 28 return 1; 29 } 30 bool HA()//判断已经出现过 31 { 32 int s=0; 33 int k=1; 34 for(int i=1;i<=3;i++) 35 { 36 for(int j=1;j<=3;j++) 37 { 38 s+=a[t].map[i][j]*k; 39 k*=8; 40 } 41 } 42 s%=3733799; 43 if(ha[s]==0) 44 { 45 ha[s]=1; 46 return 1; 47 } 48 return 0; 49 } 50 void move(int x,int y)//核心,移动 51 { 52 for(int i=0;i<4;i++) 53 { 54 int q=x+yd[i],p=y+yyd[i];//每一种情况 55 if(pd(q,p)==1) 56 { 57 for(int j=1;j<=3;j++) 58 for(int k=1;k<=3;k++) 59 a[t].map[j][k]=a[h].map[j][k]; 60 swap(a[t].map[x][y],a[t].map[q][p]); 61 step[t]=step[h]+1; 62 if(bj()) 63 { 64 cout<<step[t]; 65 flag=1; 66 return ; 67 } 68 if(HA()==1) 69 { 70 t++; 71 } 72 } 73 } 74 } 75 void search()//将栈不断进行操作到h=t结束 76 { 77 while(h<t) 78 { 79 for(int i=1;i<=3;i++) 80 for(int j=1;j<=3;j++) 81 { 82 if(a[h].map[i][j]==0) 83 move(i,j);//从0,0开始移动 84 if(flag==1) 85 return ; 86 } 87 h++;//tou++ 88 } 89 90 } 91 int main()//将其用string类型输入 92 { 93 string s; 94 cin>>s; 95 for(int i=1;i<=3;i++) 96 for(int j=1;j<=3;j++) 97 a[0].map[i][j]=s[(i-1)*3+j-1]-'0';//存入a.map数组 98 search();//搜 99 }