- 1、本文档共3页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
8数码难题
8数码难题
源程序名 8num.??? (pas,c,cpp)
可执行文件名 8num.exe
输入文件名 8num.in
输出文件名 8num.out
【问题描述】:
在 3 * 3 的棋盘上,摆 有八个棋子,每个棋子上标有 1 至 8 的某一数字。棋盘中留有一个空格。空格周围的棋子可以移到空格中。要求解的 问题是,给出一种初始布局 [ 初始状态 ] 和目标布局 [ 目标状态 ] ,找到一种移动的方法,实现从初始布局到目标布局的转变。
【输入格式】
输入由两行组成,每行8个数,分别表示初始状态和目标状态:
【输出格式】
有若干行,第一行表示最小步数 ,接下来的每行输出一步的状态,如果在6步内无法达到目标状态,输出“No solution!”。
【输入输出样例】
输入文件名: 8num.in
283164705
123804765
输出文件名:8num.out
5
283164705
283104765
203184765
023184765
123084765
123804765
【问题分析】:
这是一道典型的搜索题目,搜索产生的结点可以达到9!,再加上判重,如果不优化的话,耗时严重,关于广搜得优化我们后面的学习中再作讨论,本题只要求输出6步以内可以达到的目标,所以使用一般的广搜即可解决,问题是,如何在扩展结点的同时计算出已经走的步数,而不是找到目标状态后再逆序跟踪输出步数和步骤。我们知道,广搜是按层次搜索的,所以每搜完一层,即可视为走完一步,所以,我们只需要记录下来当前搜索了多少层,即扩展了多少层即可。我们使用变量tail2记录正在扩展的当前层的最后一个结点在队列中的位置,当head指向tail2并且扩展完tail2,说明完成一层的搜索,此时step+1,并且使tail2指向当前的tail,也就是扩展出的新的一层的尾结点。记录步数的广搜算法框架如下:
Program Bfs;
初始化,初始状态存入OPEN 表;
队列首指针head:=0;尾指针 tail:=1;tail2:=1; step:=1;
repeat
指针head后移一位,指向待扩展结点;
for I=1 to max do {max为产生子结点的规则数}
begin
if 子结点符合条件 then
begin
if新结点是目标结点 then 输出 else
if新结点与原已产生结点不重复 then tail 指针增1,把新结点存入列尾;
end;
end;
if head=tail2 then begin inc(step);tail2:=tail;end;
until(head=tail); {队列空}
另外我们需要考虑如何记录数码状态,可以使用3*3的二维数组,也可以使用长度为9的字符串。一般使用数组记录,实现起来比较简单,但是判重的时候比较麻烦,如果使用9维布尔数组来判重,那么需要很大的存储空间,不过速度会较快,如果使用字符串来记录,难以用布尔数组来判重,所以判重耗时巨大,但是字符串可以直接比较并且本题的规模也不大,只要判断6步以内是否能够达到目标状态,所以我们不妨使用字符串s来记录数码状态,用p来记录s中0的位置,0与其他数字的交换最多有四种情况:
与上方的数字交换则把p与p-3位置的字符交换位置;
与右边的数字交换则把p与p+1位置的字符交换位置;
与下方的数字交换则把p与p+3位置的字符交换位置;
与左边的数字交换则把p与p-1位置的字符交换位置;
注意特殊情况下,当p=4或7时,0不能与左边数字交换,当p=3或6时,0不能与右边数字交换,另外,所有的交换位置都不能超过1~9范围。
【上机练习】
1、8数码难题 /vijos/Problem_Show.asp?id=1469
2、黑白棋盘游戏 /vijos/Problem_Show.asp?id=1470
文档评论(0)