Vijos 八数码问题
Posted 心之所向 素履以往
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vijos 八数码问题相关的知识,希望对你有一定的参考价值。
背景
Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
格式
输入格式
输入初试状态,一行九个数字,空格用0表示
输出格式
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
样例1
样例输入1
283104765
样例输出1
4
1 /* 2 搜索过程没什么好说的 3 我只想说一下hash 4 这个判重好坑 数据太细了! 5 只好用康拓展开 6 */ 7 #include<cstdio> 8 #include<cstring> 9 #include<iostream> 10 #define MAXN 1000010 11 12 using namespace std; 13 14 int map[3][3],x,y,head,tail; 15 16 int _x[4]={0,1,0,-1}; 17 int _y[4]={1,0,-1,0}; 18 19 struct node { 20 int m[3][3]; 21 }; 22 node e[MAXN]; 23 24 char s[10]; 25 26 int step[MAXN]; 27 28 bool _hash[67338000],flag; 29 30 inline void _pre() { 31 string ss="123804765"; 32 for(int i=0;i<9;i++) { 33 map[x][y]=ss[i]-48; 34 y++; 35 if(y==3) x++,y=0; 36 } 37 x=0;y=0; 38 return; 39 } 40 41 inline bool __hash() { 42 int _Inr=0,k=1,t=1; 43 for(int i=0;i<3;i++) 44 for(int j=0;j<3;j++) { 45 _Inr+=e[tail].m[i][j]*k; 46 t++,k*=t; 47 } 48 //_Inr%=373897779; 49 if(!_hash[_Inr]) { 50 _hash[_Inr]=true; 51 return true; 52 } 53 return false; 54 } 55 56 inline bool pd(int i,int j) { 57 return i>=0&&j>=0&&i<3&&j<3; 58 } 59 60 inline bool check() { 61 for(int i=0;i<3;i++) 62 for(int j=0;j<3;j++) 63 if(e[tail].m[i][j]!=map[i][j]) return false; 64 return true; 65 } 66 67 inline void move(int p,int q) { 68 int xx,yy; 69 for(int i=0;i<4;i++) { 70 xx=p+_x[i]; 71 yy=q+_y[i]; 72 if(pd(xx,yy)) { 73 for(int a=0;a<3;a++) 74 for(int b=0;b<3;b++) 75 e[tail].m[a][b]=e[head].m[a][b]; 76 swap(e[tail].m[p][q],e[tail].m[xx][yy]); 77 step[tail]=step[head]+1; 78 if(check()) { 79 printf("%d\n",step[tail]); 80 flag=true; 81 return; 82 } 83 if(__hash()) tail++; 84 } 85 } 86 } 87 88 inline void search() { 89 while(head<tail) { 90 for(int i=0;i<3;i++) 91 for(int j=0;j<3;j++) { 92 if(e[head].m[i][j]==0) move(i,j); 93 if(flag) return; 94 } 95 head++; 96 } 97 } 98 99 int main() { 100 _pre(); 101 scanf("%s",s); 102 for(int i=0;i<strlen(s);i++) { 103 e[0].m[x][y]=s[i]-48; 104 y++; 105 if(y==3) y=0,x++; 106 } 107 tail++; 108 search(); 109 return 0; 110 }
以上是关于Vijos 八数码问题的主要内容,如果未能解决你的问题,请参考以下文章