八数码难题(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)相关推荐

  1. 洛谷P1379八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...

  2. P1379-八数码难题(BFS+A*)(代码带详细注释)

    这是本蒟蒻在洛谷通过的第一道 "提高+/省选-" 的 水 蓝题. 八数码难题是一个非常经典的BFS的题,并且P1379这道题即使是最朴素的BFS也是能够通过的,但是结果是这样: e ...

  3. 【codevs1225】八数码难题,如何精确地搜索

    1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道 ...

  4. 利用Python求解八数码难题

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

  5. 八数码难题的多种解法

    蔡自兴老师的<人工智能及其应用>这本书的第3章里面讲解了很多种搜索方法,因为看的不是很懂,所以网上就找了资源来帮助理解. 为了帮助各位更好的理解,在此,仅以八数码难题为实例来解释说明. # ...

  6. 深度优先搜索解决八数码难题

    八数码问题 以前用java写的通过深度优先瘦素解决八数码难题. 对于八数码难题来说,可以把9宫格看成一个[3][3]的二维数组,将空格位置看成0,将0可以移动的方向看成树的枝丫,分为上下左右4个方向. ...

  7. 8puzzle java 代码_八数码难题(8 puzzle)深度优先和深度优先算法

    1搜索策略 搜索策略是指在搜索过程中如何选择扩展节点的次序问题.一般来说,搜索策略就是采用试探的方法.它有两种类型:一类是回溯搜索,另一类是图搜索策略. 2盲目的图搜索策略 图搜索策略又可分为两种:一 ...

  8. 1379 八数码难题

    1379 八数码难题 这道题我本来想使用HASH+MAP来练练手,结果发现用A*+ID更简单 也就是说,这道题使用的是A算法+迭代加深算法进行一个估价函数和固定层数再加上优化的时间,来AC这一道题 首 ...

  9. 洛谷—P1379 八数码难题

    题目链接:P1379 八数码难题 题目大意: 要求最少步骤的移动方法,实现从初始布局到目标布局的转变. 解题思路: 这道题目要用到搜索中比较难的搜索方法-迭代加深的A*算法.所谓迭代加深就是每次限制搜 ...

最新文章

  1. Linux mail 命令参数
  2. 排列若干个字符串,判断是否首尾可以连接在一起
  3. java面试题:集合_Java:选择正确的集合
  4. 数据结构实验之栈:行编辑器
  5. 历史回顾——NLP问题解决方案的演变史
  6. resnet结构_来聊聊ResNet及其变种
  7. 栈实现队列(队列实现栈)
  8. 随机微分方程学习笔记04 Ito公式
  9. SEO经验分享之百度知道篇
  10. Photoshop CS3 中文版安装教程
  11. VMware系列序列号
  12. word 多级编号列表
  13. 浪潮激荡大时代,存储起航新十年
  14. MySQL之my.cnf配置文件
  15. 小鸟云服务器FTP上传中断是什么原因?解决方法总结
  16. 什么是CDN?什么又是高防CDN?
  17. 如何查看自己电脑显卡对应的cuda版本
  18. 天威诚信受邀参加第二届GIEC互联网文娱数字创新峰会
  19. 【内核笔记】博文2021回顾-2022规划
  20. RSPSS重复测量方差分析

热门文章

  1. 跟我学Springboot开发后端管理系统6:缓存框架Caffeine
  2. Java 如何设计 API 接口,实现统一格式返回?
  3. Openresty最佳案例 | 第7篇: 模块开发、OpenResty连接Redis
  4. CNN的一些可视化方法!
  5. Deep learning调参经验
  6. 刚刚,arXiv论文数破200万!没有arXiv,就没有21世纪的科研突破
  7. 零样本风格迁移:多模态CLIP文本驱动图像生成
  8. 这位挺身而出的研究生,被直接录用!
  9. “波士顿动力机器人”离上战场又近了一步,逆天了!
  10. 太鸡冻了!我用 Python 偷偷查到暗恋女生的名字