level 14
xmyyzw
楼主
广度优先搜索
在深度优先搜索算法中,深度越大的结点越先得到扩展。若把它改为深度越小的结点越先得到扩展,就是广度优先搜索法,下面通过一个具体实例来讨论广度优先算法的一般规律。
[例题4-1八数码难题]
在3X3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格。空格周围的棋子可以移到空格中。要求解的问题是:找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
例如输入:(代表从前一布局到后一布局)
2 8 3
1 6 4
7 0 5
1 2 3
8 0 4
7 6 5
[分析]
由于题目要找到的解是达到目标最少步骤,因此解题的方法为:从初始状态出发,先把移动一步后的布局全部找到,检查是否达到目标布局;如果没有,再从这些移动一步的布局出发,找到移动两步后的所有布局,再判断是否有达到目标的;如此继续,一直达到目标状态为止,输出结果。由于是按移动步数从少到多产生新布局的,所以找到的第一个目标一定是移动步数最少的一个,也就是最优解。
建立产生式系统。其中:综合数据库显然用3X3的二维数组来表示布局比较直观。用ch(i,j)表示第i行第j列格子上放的棋子数字,空格则用0表示。为了方便编程,还需存储该布局的空格位置:(si,sj);初始布局到该布局的步数,即深度dep;该布局的上一布局,即父结点的位置。这样数据库每一个元素应该是由上述几个数据组成的记录。
因为新产生的结点深度(也即从初始布局到该结点的步数)一般要比数据库原有结点大(或相等),按步数大的后扩展的要求,应该放在数据库的后面。而当前扩展的结点从数据库前面选取,即符合先产生的先扩展,后产生的后扩展规律。所以数据库的结构用队列的结构形式较合适。用上述记录为元素的数组data来表示数据库,并设置两个指针:closed为队列的首指针,open为队列的尾指针。
产生规则:原规则规定空格周围的棋子可以向空格移动。但如果换一种角度观察,也可看做空格向四周移动。这样处理更便于编程。如果空格位置在(si,sj),则有四条规则:
(1)空格向上移动: If si-1>=1 then ch(si,sj):=ch(si-1,sj);ch(si-1,sj):=0
(2)空格向下移动: If si+1<=3 then ch(si,sj):=ch(si+1,sj);ch(si+1,sj):=0
(3)空格向左移动: If sj-1>=1 then ch(si,sj):=ch(si,sj-1);ch(si,sj-1):=0
(4)空格向右移动: If sj+1<=3 then ch(si,sj):=ch(si,sj+1);ch(si,sj+1):=0
用数组Di和Hj来表示移动的行列增量,则有:
R 1 2 3 4
方向 左 上 右 下
Di 0 -1 0 1
Hj -1 0 1 0
算法设计:
program ex4_1_2;
初始化;把初始布局存入数据库data
设首指针closed:=1;尾指针open:=0
repeat
open增1,取出队列首纪录为当前被扩展节点;
for r:=1 to 4 do {r是规则编号}
begin
if 新空格位置合法 then
begin
closed 增1,把新布局存入队尾
if 新布局与队列中原有纪录重复 then 删除新产生的布局
else if 达到目标 then 输出并退出
2011年01月18日 19点01分
1
在深度优先搜索算法中,深度越大的结点越先得到扩展。若把它改为深度越小的结点越先得到扩展,就是广度优先搜索法,下面通过一个具体实例来讨论广度优先算法的一般规律。
[例题4-1八数码难题]
在3X3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格。空格周围的棋子可以移到空格中。要求解的问题是:找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
例如输入:(代表从前一布局到后一布局)
2 8 3
1 6 4
7 0 5
1 2 3
8 0 4
7 6 5
[分析]
由于题目要找到的解是达到目标最少步骤,因此解题的方法为:从初始状态出发,先把移动一步后的布局全部找到,检查是否达到目标布局;如果没有,再从这些移动一步的布局出发,找到移动两步后的所有布局,再判断是否有达到目标的;如此继续,一直达到目标状态为止,输出结果。由于是按移动步数从少到多产生新布局的,所以找到的第一个目标一定是移动步数最少的一个,也就是最优解。
建立产生式系统。其中:综合数据库显然用3X3的二维数组来表示布局比较直观。用ch(i,j)表示第i行第j列格子上放的棋子数字,空格则用0表示。为了方便编程,还需存储该布局的空格位置:(si,sj);初始布局到该布局的步数,即深度dep;该布局的上一布局,即父结点的位置。这样数据库每一个元素应该是由上述几个数据组成的记录。
因为新产生的结点深度(也即从初始布局到该结点的步数)一般要比数据库原有结点大(或相等),按步数大的后扩展的要求,应该放在数据库的后面。而当前扩展的结点从数据库前面选取,即符合先产生的先扩展,后产生的后扩展规律。所以数据库的结构用队列的结构形式较合适。用上述记录为元素的数组data来表示数据库,并设置两个指针:closed为队列的首指针,open为队列的尾指针。
产生规则:原规则规定空格周围的棋子可以向空格移动。但如果换一种角度观察,也可看做空格向四周移动。这样处理更便于编程。如果空格位置在(si,sj),则有四条规则:
(1)空格向上移动: If si-1>=1 then ch(si,sj):=ch(si-1,sj);ch(si-1,sj):=0
(2)空格向下移动: If si+1<=3 then ch(si,sj):=ch(si+1,sj);ch(si+1,sj):=0
(3)空格向左移动: If sj-1>=1 then ch(si,sj):=ch(si,sj-1);ch(si,sj-1):=0
(4)空格向右移动: If sj+1<=3 then ch(si,sj):=ch(si,sj+1);ch(si,sj+1):=0
用数组Di和Hj来表示移动的行列增量,则有:
R 1 2 3 4
方向 左 上 右 下
Di 0 -1 0 1
Hj -1 0 1 0
算法设计:
program ex4_1_2;
初始化;把初始布局存入数据库data
设首指针closed:=1;尾指针open:=0
repeat
open增1,取出队列首纪录为当前被扩展节点;
for r:=1 to 4 do {r是规则编号}
begin
if 新空格位置合法 then
begin
closed 增1,把新布局存入队尾
if 新布局与队列中原有纪录重复 then 删除新产生的布局
else if 达到目标 then 输出并退出