八数码 (Astar)
题目描述
在一个 3×3 的网格中,1∼8 这 8个数字和一个 X
恰好不重不漏地分布在这 3×3 的网格中。
例如:
1 2 3
X 4 6
7 5 8
在游戏过程中,可以把 X
与其上、下、左、右四个方向之一的数字交换(如果存在)。
我们的目的是通过交换,使得网格变为如下排列(称为正确排列):
1 2 3
4 5 6
7 8 X
例如,示例中图形就可以通过让 X
先后与右、下、右三个方向的数字交换成功得到正确排列。
交换过程如下:
1 2 3 1 2 3 1 2 3 1 2 3
X 4 6 4 X 6 4 5 6 4 5 6
7 5 8 7 5 8 7 X 8 7 8 X
把 X
与上下左右方向数字交换的行动记录为 u
、d
、l
、r
。
现在,给你一个初始网格,请你通过最少的移动次数,得到正确排列。
输入格式
输入占一行,将 3×33×3 的初始网格描绘出来。
例如,如果初始网格如下所示:
1 2 3
x 4 6
7 5 8
则输入为:1 2 3 x 4 6 7 5 8
输出格式
输出占一行,包含一个字符串,表示得到正确排列的完整行动记录。
如果答案不唯一,输出任意一种合法方案即可。
如果不存在解决方案,则输出 unsolvable
。
输入样例:
2 3 4 1 5 x 7 6 8
输出样例
ullddrurdllurdruldr
思路
首先,八数码有解判断的必要条件:逆序对的个数若为偶数个时有解,若为奇数个则无解。详见图(借,有问题则删,https://www.acwing.com/solution/content/35528/)
其次,对于使用astar优化时,因为当我们移动一个点的时候,只能上下左右间移动,因此 f(n) 预估距离的设定,这里定义为当前图各个点到最终图各个点的哈夫曼距离之和。
参考代码:
#include <bits/stdc++.h>#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)#define LL long long#define x first#define y second#define PII pair<int,int>#define PIS pair<int,string>#define PIII pair<int,PII>#define PDD pair<double,double>using namespace std;const int INF=0x3f3f3f3f;const int N=1005;const int M=1e7;const int mod=1e9+7;/*八数码有解判断的必要条件:逆序对的个数若为偶数个时有解,若为奇数个则无解。*///当前点到终点的预估距离,每个位置点距离自己正确位置的哈夫曼距离和// abs(xs-xe)+abs(ys-ye);int f(string state){int res = 0;int len=state.length();for(int i=0;i<len;i++){if(state[i] != 'x'){int t = state[i] - '1';res += abs(i/3 - t/3)+abs(i%3 - t%3);}}return res;}string start; //存初始状态int dir[4][2]={-1,0,1,0,0,-1,0,1};char go[]="udlr";string astar(){//最终状态string end="12345678x";map<string , int> dis; //到这个状态的实际距离map<string , pair<string,char> >pre; //到这个状态的,前个状态和动作priority_queue<PIS,vector<PIS>,greater<PIS> >q;q.push({f(start),start});dis[start]=0;while(q.size()){auto tmp=q.top();q.pop();//当前状态string state=tmp.y;//到达最终状态,退出if(state==end)break;//获取当前步数int step=dis[state];int x,y;//找到操作"X"的位置for(int i=0;i<9;i++){if(state[i]=='x'){x=i/3;y=i%3;break;}}//存储当前状态string source=state;//开始向4个方向扩展for(int i=0,nx,ny;i<4;i++){nx=x+dir[i][0];ny=y+dir[i][1];if(nx<0 || nx>=3 || ny<0 || ny>=3)continue;//交换2点位置swap(state[x*3+y],state[nx*3+ny]);/*更新状态的2种情况:1.若移动后的状态不存在2.若移动后的状态所用步数大于当前状态,则表示移动后的状态下都可以被更新*/if(dis.count(state)==0 || dis[state]>step+1){//更新实际距离dis[state]=step+1;//记录前驱,{前一个状态,动作}pre[state]={source,go[i]};q.push({dis[state]+f(state),state});}//回溯2点位置swap(state[x*3+y],state[nx*3+ny]);}}//反向遍历操作结果string res="";while(end!=start){res+=pre[end].y;end=pre[end].x;}reverse(res.begin(),res.end());return res;}int main(){char c;string str; //用来判断逆序对for(int i=0;i<9;i++){cin>>c;if(c!='x')str+=c;start+=c;}int cnt=0; //逆序对个数for(int i=0;i<str.length();i++){for(int j=i+1;j<str.length();j++){if(str[i]>str[j])cnt++;}}//奇数个,无解if(cnt&1)cout<<"unsolvable\n";//偶数个,存在解else cout<<astar()<<"\n";system("pause");return 0;}
八数码 (Astar)相关推荐
- AcWing 179. 八数码 178. 第K短路 (A-star)
A-star 算法 算法证明略 做题步骤: 如果搜索空间过大,考虑使用A*算法,正常做真实距离,思考估价函数,验证估价函数的正确性,队列换成优先队列,新加一维 真实+估计,终点出队即为答案 AcWin ...
- 基于Python实现的AStar求解八数码问题
资源下载地址:https://download.csdn.net/download/sheziqiong/86776612 资源下载地址:https://download.csdn.net/downl ...
- Astar、A星算法解决八数码问题--python实现
一.问题描述 数码问题又称9宫问题,与游戏"华容道"类似.意在给定的3*3棋格的8个格子内分别放一个符号,符号之间互不相同,余下的一格为空格.并且通常把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短路的,.. ...
- 《人工智能》实验二——搜索技术(八数码问题)
必须记住下一步还可以走哪些点--OPEN表(记录还没有扩展的点) 必须记住哪些点走过了--CLOSED表(记录已经扩展的点 广度优先搜索 在应用BFS算法进行八数码问题搜索时需要open和closed ...
- Nilsson's sequence score算法解决八数码问题解释
解决了最近一个人工智能关于解决八数码难题的作业. 图可能看不清,除了黑块外其他位置是英文字母ABCDEFGH A*:f(n)=g(n)+h(n) 其中f为总花费,g为已知花费(深度),h为估计花费 关 ...
- 学习笔记--八数码问题
题目链接 https://www.luogu.org/problemnew/show/P1379 分析 经典的八数码问题,有双向BFS和\(IDA*\)的方法,这里使用的是\(A*\)启发式搜索. 简 ...
- 使用Muduo完成数独和八数码问题求解服务器
在剖析完Muduo网络库源码之后,我们试着完成一个高效的数独和八数码问题求解服务器. 先说说为什么要选择这两个问题?数独问题一直是陈硕老师很喜欢的问题,在muduo网络库中多次提到并有示例.八数码问题 ...
- 习题:八数码难题(双向BFS)
八数码难题(wikioi1225) [题目描述] 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出 ...
- AI 八数码A_star算法问题-实验报告
一 题目要求: 八数码问题的A星搜索算法实现 要求:设计估价函数,并采用c或python编程实现,以八数码为例演示A星算法的搜索过程,争取做到直观.清晰地演示算法,代码要适当加注释. ...
最新文章
- HarmonyOS Text设置换行
- android数据库降级_android——数据库版本升/降级问题
- Lucene 4.X 倒排索引原理与实现: (3) Term Dictionary和Index文件 (FST详细解析)——直接看例子就明白了!!!...
- 【BZOJ4405】【WC2016】挑战NPC(带花树)
- python实现WebsocketServer 服务端
- 发现一个骨灰级图形学大神的博客
- CDOJ 1269 ZhangYu Speech
- 普通人改变命运最关键的这几种方法
- python子类分配
- Python-pillow库显示MNIST图片的方法
- 面向连接服务与无连接服务
- 每日一题(44)—— 请列举一个软件中时间换空间或者空间换时间的例子
- excel 某个单元格不是等于空值,Excel返回第一个与所有非空单元格及统计数量,把空单元格替换为0...
- U3D_Shader编程(第一篇:快速入门篇)
- Java反射 二三事
- [励志][经验]《异类》 -- 格拉德威尔(美)
- 计算机中的一些基本概念(速度,比特,门,电路图)
- 本文主要讲述如何开通自己的博客。若读者不想或已经知道如何开通使用博客,那么就可以跳过。 一直以来,想把自己在学习过程中遇到的问题及解决办法共享给志同道合的人,那么如何分享自己的见解呢?有如下方法
- 邮件狂人告诉你:如何打造最强邮件处理流
- 手把手教你使用ModelArts的自动学习识别毒蘑菇分类