1225 八数码难题
Posted 神犇(shenben)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1225 八数码难题相关的知识,希望对你有一定的参考价值。
题目描述 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
详见试题
#include<cstdio> #include<cstring> #include<iostream> #include<map> using namespace std; struct node{ int shu[4][4]; int step,xs,ys; }a,b,y; map<string,int>s; int n_best=20;//题目保证有解,大约最大步数为20 bool pan(node x){//判断是否达到目标状态 for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) if(a.shu[i][j]!=x.shu[i][j]) return 0; return 1; } void dfs(node x){ if(x.step>n_best) return ; string q=""; for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) q=q+(char)(x.shu[i][j]+‘0‘);//用到了map if(s[q]<x.step&&s[q]!=0) return ;//避免重搜 s[q]=x.step; if(pan(x)){ n_best=x.step;//记录(因为第一次不一定是最优) return ;//跳出 } x.step++;//步数+ 1,下面用y做temp来dfs if(x.xs<3){//可以向右 y=x; swap(y.shu[x.xs][x.ys],y.shu[x.xs+1][x.ys]);//移动‘0’的位置 y.xs++;//0’的位置 改变了 dfs(y);//下一个状态,dfs,以此类推 } if(x.xs>1){//可以向左 y=x; swap(y.shu[x.xs][x.ys],y.shu[x.xs-1][x.ys]); y.xs--; dfs(y); } if(x.ys<3){//可以向下 y=x; swap(y.shu[x.xs][x.ys],y.shu[x.xs][x.ys+1]); y.ys++; dfs(y); } if(x.ys>1){//可以向上 y=x; swap(y.shu[x.xs][x.ys],y.shu[x.xs][x.ys-1]); y.ys--; dfs(y); } return ; } int main(){ for(int i=1;i<=3;i++) for(int j=1;j<=3;j++){ char dd=getchar(); b.shu[i][j]=dd-‘0‘; if(dd==‘0‘){//记录‘0‘的位置 b.xs=i; b.ys=j; } } for(int i=1;i<=3;i++) a.shu[1][i]=i;//a.shu为目标状态:123804765 a.shu[2][1]=8;a.shu[2][2]=0;a.shu[2][3]=4; a.shu[3][1]=7;a.shu[3][2]=6;a.shu[3][3]=5; b.step=0; dfs(b); printf("%d\n",n_best); return 0; }
双向搜索+康托展开 看不懂
//hzwer的代码,未测 #include<iostream> #include<cstring> using namespace std; struct data{int a[3][3];}d[2][362880];//0正向搜索,1反向搜索 int xx[4]={1,-1,0,0},yy[4]={0,0,1,-1}; int mp[2][362881],step[2][362880],flag=0; int t[2],w[2]={1,1}; void sp(int &a,int &b){int t=a;a=b;b=t;} bool pd(int x,int y){if(x>=3||y>=3||x<0||y<0)return 0;return 1;} int cantor(int x){ int fac[10]={1,1,2,6,24,120,720,5040,40320,362880},m[9]; for(int i=9;i>=1;i--){m[i]=x%10;x/=10;} int s=0; for(int i=1;i<=9;i++) { int temp=0; for(int j=i+1;j<=9;j++) if(m[j]<m[i])temp++; s+=fac[9-i]*temp; } return s; } int Hash(int a[3][3]){ int x=0,k=1; for(int i=2;i>=0;i--) for(int j=2;j>=0;j--) {x+=a[i][j]*k;k*=10;} return cantor(x); } void search(int k){ for(int i=0;i<3;i++) for(int j=0;j<3;j++) d[k][w[k]].a[i][j]=d[k][t[k]].a[i][j]; int x,y; for(int i=0;i<3;i++) for(int j=0;j<3;j++) if(d[k][t[k]].a[i][j]==0){x=i;y=j;break;} for(int dir=0;dir<4;dir++) { for(int i=0;i<3;i++) for(int j=0;j<3;j++) d[k][w[k]].a[i][j]=d[k][t[k]].a[i][j]; int p=x+xx[dir],q=y+yy[dir]; if(pd(p,q)) { sp(d[k][w[k]].a[x][y],d[k][w[k]].a[p][q]); int temp=Hash(d[k][w[k]].a); if(mp[k][temp]==-1) { step[k][w[k]]=step[k][t[k]]+1; mp[k][temp]=step[k][w[k]]; if(mp[0][temp]!=-1&&mp[1][temp]!=-1) { cout<<mp[0][temp]+mp[1][temp]; flag=1; return; } w[k]++; } } } t[k]++; } void doit(){ while(!flag){ if(w[0]-t[0]<=w[1]-t[1])search(0); else search(1);} } int main(){ string str; cin>>str; int k=0; for(int i=0;i<3;i++) for(int j=0;j<3;j++) { d[0][0].a[i][j]=str[k]-‘0‘; k++; } d[1][0]=(data){1,2,3,8,0,4,7,6,5}; memset(mp,-1,sizeof(mp)); mp[0][Hash(d[0][0].a)]=mp[1][Hash(d[1][0].a)]=0; doit(); return 0; }
以上是关于1225 八数码难题的主要内容,如果未能解决你的问题,请参考以下文章