习题:八数码难题(双向BFS)
八数码难题(wikioi1225)
【题目描述】
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
【输入描述】
输入初试状态,一行九个数字,空格用0表示。
【输出描述】
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)。
【样例输入 】
283104765
【样例输出】
4
分析:
很经典题目,题意不解释了。
看到最小步骤会想到广搜,本题可以看成是空格移动达到目标状态的问题,记录空格位置和棋盘状态,加入队列不断增加节点入队。同时注意判重,将棋盘转换为九位数(如果第一个数字为0则是八位数),用hash表解决。这样就可以过这道题了。
但是为了达到更好的时间效率,可以使用双向广搜。
双向宽搜,顾名思义就是从两边搜,适用于已知起始状态和目标状态,求最短步骤的题目。
我们可以开两类数组,分别表示正方方向搜索的队列,然后初始,目标状态分别入对应队列,进行扩展节点,直到两个方向搜索相遇时即得出最短步骤。
出于优化时间的目的,我们往往先搜队列中节点少的方向,轮流进行。
具体讲就是:两个方向根据队列中节点数交替扩展节点,每扩展一个节点为,在本队列判重后还要在另一个方向的队列中找是否出现,出现说明相遇,输出最短步骤为正方方向扩展到该节点所需最短步骤。
注意双向广搜时,反方向扩展节点时操作与正方向相反,比如向左移动要变为向右移动,但这点对本题没有影响。
解释一下
head,tail表示队头队尾指针,v表示最短步骤,w是棋盘状态,px,py表示空格位置。
0表示正方向,1表示反方向。彼此可用1-x转换。
以下就是自己写的了双向广搜+hash判重的八数码AC程序。
代码
program puzzle; constmaxn=10007; typehh=^node;node=recorddata:longint;text:longint;next:hh;end; vardx:array[1..4]of longint=(0,0,1,-1);dy:array[1..4]of longint=(1,-1,0,0);hash:array[0..1,0..maxn]of hh;head,tail:array[0..1]of longint;w:array[0..1,0..362881,1..3,1..3]of longint;b:array[1..3,1..3]of longint;px,py,v:array[0..1,0..362881]of longint;n,i,m,j,x,y,s,h,t,k,r:longint;c:char; function haha(t,x:longint):boolean;var i,j,xx:longint;p:hh;beginxx:=x mod maxn;new(p);p:=hash[t,xx];while p<>nil dobeginif p^.data=x then begin r:=p^.text; exit(true); end;p:=p^.next;end;exit(false);end; procedure put(t,x:longint); var q:hh;xx:longint; beginxx:=x mod maxn;new(q);q^.data:=x; q^.text:=tail[t]; q^.next:=hash[t,xx];hash[t,xx]:=q; end; procedure bfs(x:longint); var i,j,u,l,ans,xx,yy,g,tmp:longint; beginhead[x]:=head[x]+1;for i:=1 to 4 dobegin b:=w[x,head[x]];xx:=px[x,head[x]]+dx[i]; yy:=py[x,head[x]]+dy[i];tmp:=b[xx,yy]; b[xx,yy]:=b[px[x,head[x]],py[x,head[x]]];b[px[x,head[x]],py[x,head[x]]]:=tmp;g:=100000000; ans:=0;for u:=1 to 3 do beginfor l:=1 to 3 dobegin ans:=ans+g*b[u,l]; g:=g div 10; end;end;if (xx>0)and(xx<=3)and(yy>0)and(yy<=3)and(haha(x,ans)=false) thenbegintail[x]:=tail[x]+1; px[x,tail[x]]:=xx; py[x,tail[x]]:=yy; w[x,tail[x]]:=b; v[x,tail[x]]:=v[x,head[x]]+1; put(x,ans);if haha(1-x,ans)=true thenbeginwriteln(v[x,tail[x]]+v[1-x,r]); k:=1; break;end;//在另一个方向的队列中查找该节点end;if k=1 then break;end;if k=1 then exit; end; begint:=100000000;for i:=1 to 3 do beginfor j:=1 to 3 dobegin read(c);if c='0' then begin x:=i; y:=j;end;w[1,1,i,j]:=ord(c)-48; s:=s+w[1,1,i,j]*t; t:=t div 10; end;end;put(0,123804765); put(1,s); k:=0;//存入两个hash数组w[0,1,1,1]:=1; w[0,1,1,2]:=2; w[0,1,1,3]:=3;w[0,1,2,1]:=8; w[0,1,2,2]:=0; w[0,1,2,3]:=4;w[0,1,3,1]:=7; w[0,1,3,2]:=6; w[0,1,3,3]:=5;v[0,1]:=0; v[1,1]:=0; px[0,1]:=2; py[0,1]:=2; px[1,1]:=x; py[1,1]:=y;head[0]:=0; head[1]:=0; tail[0]:=1; tail[1]:=1;repeatif (tail[0]>head[0])and((tail[0]-head[0]<tail[1]-head[1])or(tail[1]<=head[1]))then bfs(0) else if tail[1]>head[1] then bfs(1);//交替扩展节点if k=1 then break;until ((head[0]>=tail[0])or(tail[0]>=362880))and((head[1]>=tail[1])or(tail[1]>=362880)); end.
View Code
使用双向广搜,时间效率大大提高,两种方法在不加其它优化的时间效率对比
广搜+hash
双向广搜+hash
转载于:https://www.cnblogs.com/qtyytq/p/4265757.html
习题:八数码难题(双向BFS)相关推荐
- 洛谷P1379八数码难题
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...
- P1379-八数码难题(BFS+A*)(代码带详细注释)
这是本蒟蒻在洛谷通过的第一道 "提高+/省选-" 的 水 蓝题. 八数码难题是一个非常经典的BFS的题,并且P1379这道题即使是最朴素的BFS也是能够通过的,但是结果是这样: e ...
- 【codevs1225】八数码难题,如何精确地搜索
1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道 ...
- 利用Python求解八数码难题
实验目的 实验内容 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格,与空格相邻的棋子可以移到空格中.要求解决的问题 ...
- 八数码难题的多种解法
蔡自兴老师的<人工智能及其应用>这本书的第3章里面讲解了很多种搜索方法,因为看的不是很懂,所以网上就找了资源来帮助理解. 为了帮助各位更好的理解,在此,仅以八数码难题为实例来解释说明. # ...
- 深度优先搜索解决八数码难题
八数码问题 以前用java写的通过深度优先瘦素解决八数码难题. 对于八数码难题来说,可以把9宫格看成一个[3][3]的二维数组,将空格位置看成0,将0可以移动的方向看成树的枝丫,分为上下左右4个方向. ...
- 8puzzle java 代码_八数码难题(8 puzzle)深度优先和深度优先算法
1搜索策略 搜索策略是指在搜索过程中如何选择扩展节点的次序问题.一般来说,搜索策略就是采用试探的方法.它有两种类型:一类是回溯搜索,另一类是图搜索策略. 2盲目的图搜索策略 图搜索策略又可分为两种:一 ...
- 1379 八数码难题
1379 八数码难题 这道题我本来想使用HASH+MAP来练练手,结果发现用A*+ID更简单 也就是说,这道题使用的是A算法+迭代加深算法进行一个估价函数和固定层数再加上优化的时间,来AC这一道题 首 ...
- 洛谷—P1379 八数码难题
题目链接:P1379 八数码难题 题目大意: 要求最少步骤的移动方法,实现从初始布局到目标布局的转变. 解题思路: 这道题目要用到搜索中比较难的搜索方法-迭代加深的A*算法.所谓迭代加深就是每次限制搜 ...
最新文章
- Linux mail 命令参数
- 排列若干个字符串,判断是否首尾可以连接在一起
- java面试题:集合_Java:选择正确的集合
- 数据结构实验之栈:行编辑器
- 历史回顾——NLP问题解决方案的演变史
- resnet结构_来聊聊ResNet及其变种
- 栈实现队列(队列实现栈)
- 随机微分方程学习笔记04 Ito公式
- SEO经验分享之百度知道篇
- Photoshop CS3 中文版安装教程
- VMware系列序列号
- word 多级编号列表
- 浪潮激荡大时代,存储起航新十年
- MySQL之my.cnf配置文件
- 小鸟云服务器FTP上传中断是什么原因?解决方法总结
- 什么是CDN?什么又是高防CDN?
- 如何查看自己电脑显卡对应的cuda版本
- 天威诚信受邀参加第二届GIEC互联网文娱数字创新峰会
- 【内核笔记】博文2021回顾-2022规划
- RSPSS重复测量方差分析