问题描述

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始状态和目标状态,找到一种最少步骤的移动方法,实现从初始状态到目标状态的转变。
例如:

输入样例:

输入棋子在棋盘的初始状态及目标状态,注第一个3×3为初始状态,第二个3×3为目标状态,且数字之间以空格分开,如:

3 1 2
4 0 5
6 7 8
0 1 2
3 4 5
6 7 8

输出样例:

输出棋盘初始状态及每步的移动结果,直到目标状态,如:

initial
3 1 2
4 0 5
6 7 8

step 1
3 1 2
0 4 5
6 7 8
step 2
0 1 2
3 4 5
6 7 8

总代码

1.盲搜(无向导搜索)
采用广搜的方法,实现无向导搜索。

#include<iostream>
#include<map>
#include<queue>using namespace std;queue<int>Qtmp;
map<int,int>pointex;
map<int,int>count;
map<int,int>qifazhi;
map<int,int>pointdir;
int resultsum[100];int dir[4][2]={-1,0,0,1,1,0,0,-1};
int point[3][3];
int r,c;int qifa(int sum0,int end0){int result=0;if((sum0/100000000==0)&&(end0/100000000==0)){result++;}while((sum0%10!=0)&&(end0%10!=0)&&(sum0/10!=0)){if(sum0%10==end0%10){result++;}sum0=sum0/10;end0=end0/10;}return result;
}int move(int u,int d)
{int tmp=0;      int nr=r+dir[d][0];int nc=c+dir[d][1];point[r][c]=point[nr][nc];point[nr][nc]=0;for(int i=0;i<3;i++){for(int j=0;j<3;j++)tmp=tmp*10+point[i][j];}return tmp;
}int formulate(int s,int endsum0)
{Qtmp.push(s);pointex[s]=1;count[s]=0;int number=0;while(Qtmp.size()){int u,v;u=Qtmp.front();Qtmp.pop();if(u==endsum0){return count[u];}int minqifa=move(u,0);for(int i=0;i<4;i++){bool fool=true;int uu=u;for(int ii=2;ii>=0;ii--){for(int jj=2;jj>=0;jj--){point[ii][jj]=uu%10;uu/=10;if(point[ii][jj]==0){r=ii;c=jj;}}}if((i==0&&r==0)||(i==1&&c==2)||(i==2&&r==2)||(i==3&&c==0)){fool=false;}if(fool){v=move(u,i);if(!pointex[v]){int qifatmp=qifa(v,endsum0);if(qifatmp<=minqifa){pointex[v]=1;count[v]=count[u]+1;pointdir[v]=i;Qtmp.push(v);number++;}}}}if(number>100){return -1;}}return -1;
}int main()
{int end[3][3];int endsum=0;int beginsum=0;int result;for(int i=0;i<3;i++){for(int j=0;j<3;j++){cin>>point[i][j];beginsum=beginsum*10+point[i][j];}}for(int i=0;i<3;i++){for(int j=0;j<3;j++){cin>>end[i][j];endsum=endsum*10+end[i][j];}}result=formulate(beginsum,endsum);resultsum[result+1]=endsum;int endr0,endc0;int temp=endsum;for(int i=2;i>=0;i--){for(int j=2;j>=0;j--){end[i][j]=temp%10;temp/=10;if(end[i][j]==0){endr0=i;endc0=j;}}}int tmpsum;//cout<<result<<endl;if(result==-1){cout<<"no answer"<<endl;}if(result!=-1){for(int i=result;i>0;i--){if(pointdir[endsum]==0){end[endr0][endc0]=end[endr0+1][endc0];end[endr0+1][endc0]=0;tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2];resultsum[i]=tmpsum;endr0=endr0+1;}if(pointdir[endsum]==1){end[endr0][endc0]=end[endr0][endc0-1];end[endr0][endc0-1]=0;tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2];resultsum[i]=tmpsum;endc0=endc0-1;}if(pointdir[endsum]==2){end[endr0][endc0]=end[endr0-1][endc0];end[endr0-1][endc0]=0;tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2];resultsum[i]=tmpsum;endr0=endr0-1;}if(pointdir[endsum]==3){end[endr0][endc0]=end[endr0][endc0+1];end[endr0][endc0+1]=0;tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2];resultsum[i]=tmpsum;endc0=endc0+1;}endsum=tmpsum;}for(int i=1;i<result+2;i++){if(i==1){cout<<"initial"<<endl;}else{cout<<"step "<<i-1<<endl;}int k=0;for(int j=100000000;j>0;j=j/10){cout<<resultsum[i]/j<<" ";resultsum[i]=resultsum[i]-resultsum[i]/j*j;k++;if(k%3==0){cout<<endl;}}cout<<endl;}}system("pause");return 0;
}

2.启发式搜索(有向导搜索)
新增启发函数,实现有向导搜索,大大减少搜索时间。

#include<iostream>
#include<map>
#include<queue>using namespace std;queue<int>Qtmp;
map<int,int>pointex;
map<int,int>count;
map<int,int>pointdir;
int resultsum[100];int dir[4][2]={-1,0,0,1,1,0,0,-1};
int point[3][3];
int r,c;int qifa(int sum0,int end0){int result=0;if((sum0/100000000==0)&&(end0/100000000==0)){result++;}while((sum0%10!=0)&&(end0%10!=0)&&(sum0/10!=0)){if(sum0%10==end0%10){result++;}sum0=sum0/10;end0=end0/10;}return result;
}int move(int u,int d)
{int tmp=0;      int nr=r+dir[d][0];int nc=c+dir[d][1];point[r][c]=point[nr][nc];point[nr][nc]=0;for(int i=0;i<3;i++){for(int j=0;j<3;j++)tmp=tmp*10+point[i][j];}return tmp;
}int formulate(int s,int endsum0)
{Qtmp.push(s);pointex[s]=1;count[s]=0;int number=0;while(Qtmp.size()){int u,v;u=Qtmp.front();Qtmp.pop();if(u==endsum0){return count[u];}int minqifa=100;for(int i=0;i<4;i++){bool fool=true;int uu=u;for(int ii=2;ii>=0;ii--){for(int jj=2;jj>=0;jj--){point[ii][jj]=uu%10;uu/=10;if(point[ii][jj]==0){r=ii;c=jj;}}}if((i==0&&r==0)||(i==1&&c==2)||(i==2&&r==2)||(i==3&&c==0)){fool=false;}if(fool){v=move(u,i);if(!pointex[v]){int qifatmp=qifa(v,endsum0);if(qifatmp<=minqifa){minqifa=qifatmp;pointex[v]=1;count[v]=count[u]+1;pointdir[v]=i;Qtmp.push(v);number++;}}}}if(number>100){return -1;}}return -1;
}int main()
{int end[3][3];int endsum=0;int beginsum=0;int result;for(int i=0;i<3;i++){for(int j=0;j<3;j++){cin>>point[i][j];beginsum=beginsum*10+point[i][j];}}for(int i=0;i<3;i++){for(int j=0;j<3;j++){cin>>end[i][j];endsum=endsum*10+end[i][j];}}result=formulate(beginsum,endsum);resultsum[result+1]=endsum;int endr0,endc0;int temp=endsum;for(int i=2;i>=0;i--){for(int j=2;j>=0;j--){end[i][j]=temp%10;temp/=10;if(end[i][j]==0){endr0=i;endc0=j;}}}int tmpsum;//cout<<result<<endl;if(result==-1){cout<<"no answer"<<endl;}if(result!=-1){for(int i=result;i>0;i--){if(pointdir[endsum]==0){end[endr0][endc0]=end[endr0+1][endc0];end[endr0+1][endc0]=0;tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2];resultsum[i]=tmpsum;endr0=endr0+1;}if(pointdir[endsum]==1){end[endr0][endc0]=end[endr0][endc0-1];end[endr0][endc0-1]=0;tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2];resultsum[i]=tmpsum;endc0=endc0-1;}if(pointdir[endsum]==2){end[endr0][endc0]=end[endr0-1][endc0];end[endr0-1][endc0]=0;tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2];resultsum[i]=tmpsum;endr0=endr0-1;}if(pointdir[endsum]==3){end[endr0][endc0]=end[endr0][endc0+1];end[endr0][endc0+1]=0;tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2];resultsum[i]=tmpsum;endc0=endc0+1;}endsum=tmpsum;}for(int i=1;i<result+2;i++){if(i==1){cout<<"initial"<<endl;}else{cout<<"step "<<i-1<<endl;}int k=0;for(int j=100000000;j>0;j=j/10){cout<<resultsum[i]/j<<" ";resultsum[i]=resultsum[i]-resultsum[i]/j*j;k++;if(k%3==0){cout<<endl;}}cout<<endl;}}system("pause");return 0;
}

运行结果

八数码问题(C++)相关推荐

  1. 习题:八数码难题(双向BFS)

    八数码难题(wikioi1225) [题目描述] 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出 ...

  2. AI 八数码A_star算法问题-实验报告

    一 题目要求: 八数码问题的A星搜索算法实现         要求:设计估价函数,并采用c或python编程实现,以八数码为例演示A星算法的搜索过程,争取做到直观.清晰地演示算法,代码要适当加注释. ...

  3. 八数码问题及A*算法

    一.八数码问题 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格,与空格相邻的棋子可以移到空格中.要求解决的问题是: ...

  4. A*算法解决八数码问题 Java语言实现

    A*算法解决八数码问题 Java语言实现 参考文章: (1)A*算法解决八数码问题 Java语言实现 (2)https://www.cnblogs.com/beilin/p/5981483.html ...

  5. hdu1043 经典的八数码问题 逆向bfs打表 + 逆序数

    题意: 题意就是八数码,给了一个3 * 3 的矩阵,上面有八个数字,有一个位置是空的,每次空的位置可以和他相邻的数字换位置,给你一些起始状态 ,给了一个最终状态,让你输出怎么变换才能达到目的. 思路: ...

  6. 八数码 poj 1077 广搜 A* IDA*

    经典的八数码问题,有人说不做此题人生不完整,哈哈. 状态总数是9! = 362880 种,不算太多,可以满足广搜和A*对于空间的需求. 状态可以每次都动态生成,也可以生成一次存储起来,我用的动态生成, ...

  7. hdu 1043 ,pku 1077 Eight ,八数码问题

    某位神牛曾说过,此题是涉及到人生完不完整的一道题.. Goodness大牛曾总结了 八数码的八重境界 : http://www.cnblogs.com/goodness/archive/2010/05 ...

  8. HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法

    先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...

  9. 【 HDU1043-经典BFS+康拓展开 八数码】 (待更)

    给定一个序列,由1~8数字和字母x组成,表示的是一个3*3的矩形.每次操作x都能与相邻的数字交换,问如何操作才能使得序列为{1,2,3,4,5,6,7,8,x}. //多组数据-需要计算全部路径后直接 ...

  10. 算法提高课-搜索-A*(A star)算法-AcWing 179. 八数码:A星算法求解

    题目分析 来源:acwing 分析: A*算法是什么呢? A算法是一种bfs的变式,需要用到一个"估价函数",用来计算任意状态到目标状态所需代价的估计值.然后在搜索中,维护一个堆, ...

最新文章

  1. 【机器视觉】 translate_measure算子
  2. 插入排序之表插入排序
  3. GAN —— 《Generative Adversarial Nets》
  4. Java多线程学习七:线程池的 4 种拒绝策略和 6 种常见的线程池
  5. csv解析java_Java CSV解析器
  6. nodejs koa2 mysql_springboot动态加载sigar - SegmentFault 思否
  7. windows C盘瘦身
  8. FIX - 克隆虚拟机NAT模式网络不通、不稳定、vMnet8网络故障、网卡冲突、ssh连接慢
  9. java 佛祖保佑_佛祖保佑,永无bug
  10. TeXstudio-粗体斜体无法显示
  11. 剑指offer-二叉树(python)
  12. 软件体系结构--《Software.architecture.perspectives.on.an.emerging.discipline》
  13. pagerank简单实现
  14. 杭州SFDC开发者大会精彩片段(前端篇)
  15. OpenAtom OpenHarmony分论坛圆满举办,生态与产业发展迈向新征程
  16. 打印10 * 10的表格
  17. 点云数据集开源大汇总
  18. 概率基础 · 联合概率 边缘概率 prior posterior likelihood
  19. Day01-Java高级
  20. PR视频剪辑中如何制作抖音上的竖屏且添加模糊的视频效果

热门文章

  1. Java 字符串类型
  2. Java+spring 基于ssm的网络作业提交与批改系统#毕业设计
  3. perl dbi mysql 参数_Perl数据库DBI接口简介【转载】
  4. lasagne模型参数的查看、保存和读取
  5. MassGrid(MGD)双周报第29期(4.13-4.26)
  6. eclipse serch查询的页面只能打开一个
  7. 考试如何用计算机,高会考试计算器长什么样?如何使用?一文说全了
  8. 免费计算机群,获得大量的微信群的三种方法
  9. vsb asc_vsb电力线故障检测kaggle竞争
  10. 需求分析怎么写:Volere版需求规格说明书