好久没搞这些东西了...想了十分钟才勉强回忆起来... 写了三个钟头...好累啊... 四种算法是DFS,BFS,Heuristic DFS, Heuristic BFS (A*) 用了两张障碍表,一张是典型的迷宫:
char Block[SY][SX]= {{1,1,1,1,1,1,1,1,1,1,1 }, {1,0,1,0,1,0,0,0,0,0,1 }, {1,0,1,0,0,0,1,0,1,1,1 }, {1,0,0,0,1,0,1,0,0,0,1 }, {1,0,1,1,0,0,1,0,0,1,1 }, {1,0,1,0,1,1,0,1,0,0,1 }, {1,0,0,0,0,0,0,0,1,0,1 }, {1,0,1,0,1,0,1,0,1,0,1 }, {1,0,0,1,0,0,1,0,1,0,1 }, {1,1,1,1,1,1,1,1,1,1,1 }};
第二张是删掉一些障碍后的:
char Block[SY][SX]= {{1,1,1,1,1,1,1,1,1,1,1 }, {1,0,1,0,1,0,0,0,0,0,1 }, {1,0,1,0,0,0,1,0,1,1,1 }, {1,0,0,0,0,0,1,0,0,0,1 }, {1,0,0,1,0,0,1,0,0,1,1 }, {1,0,1,0,0,1,0,1,0,0,1 }, {1,0,0,0,0,0,0,0,1,0,1 }, {1,0,1,0,0,0,1,0,1,0,1 }, {1,0,0,1,0,0,1,0,0,0,1 }, {1,1,1,1,1,1,1,1,1,1,1 }};
结果: 尝试节点数 合法节点数 步数 深度优先 416/133 110/43 19/25 广度优先 190/188 48/49 19/15 深度+启发 283/39 82/22 19/19 广度+启发 189/185 48/49 19/15
所以可以看出深度+启发是最好的,效率高路径也挺短。A*第一是不真实二是慢三是空间消耗较大。
附:dfs+heu的源程序,bc++ 3.1通过
#include <iostream.h> #include <memory.h> #include <stdlib.h>
#define SX 11 //宽
#define SY 10 //长
int dx[4]={0,0,-1,1}; //四种移动方向对x和y坐标的影响
int dy[4]={-1,1,0,0};
/*char Block[SY][SX]= //障碍表 {{ 1,1,1,1,1,1,1,1,1,1,1 }, { 1,0,1,0,1,0,0,0,0,0,1 }, { 1,0,1,0,0,0,1,0,1,1,1 }, { 1,0,0,0,0,0,1,0,0,0,1 }, { 1,0,0,1,0,0,1,0,0,1,1 }, { 1,0,1,0,0,1,0,1,0,0,1 }, { 1,0,0,0,0,0,0,0,1,0,1 }, { 1,0,1,0,0,0,1,0,1,0,1 }, { 1,0,0,1,0,0,1,0,0,0,1 }, { 1,1,1,1,1,1,1,1,1,1,1 }};*/
char Block[SY][SX]= //障碍表
{{ 1,1,1,1,1,1,1,1,1,1,1 }, { 1,0,1,0,1,0,0,0,0,0,1 }, { 1,0,1,0,0,0,1,0,1,1,1 }, { 1,0,0,0,1,0,1,0,0,0,1 }, { 1,0,1,1,0,0,1,0,0,1,1 }, { 1,0,1,0,1,1,0,1,0,0,1 }, { 1,0,0,0,0,0,0,0,1,0,1 }, { 1,0,1,0,1,0,1,0,1,0,1 }, { 1,0,0,1,0,0,1,0,1,0,1 }, { 1,1,1,1,1,1,1,1,1,1,1 }};
int MaxAct=4; //移动方向总数
char Table[SY][SX]; //已到过标记
int Level=-1; //第几步
int LevelComplete=0; //这一步的搜索是否完成
int AllComplete=0; //全部搜索是否完成
char Act[1000]; //每一步的移动方向,搜索1000步,够了吧?
int x=1,y=1; //现在的x和y坐标
int TargetX=9,TargetY=8; //目标x和y坐标
int sum1=0,sum2=0;
void Test( ); void Back( ); int ActOK( ); int GetNextAct( );
void main( ) { memset(Act,0,sizeof(Act)); //清零
memset(Table,0,sizeof(Table)); Table[y][x]=1; //做已到过标记
while (!AllComplete) //是否全部搜索完
{ Level++;LevelComplete=0; //搜索下一步
while (!LevelComplete) { Act[Level]=GetNextAct( ); //改变移动方向
if (Act[Level]<=MaxAct) sum1++; if (ActOK( )) //移动方向是否合理
{ sum2++; Test( ); //测试是否已到目标
LevelComplete=1; //该步搜索完成
} else { if (Act[Level]>MaxAct) //已搜索完所有方向
Back( ); //回上一步
if (Level<0) //全部搜索完仍无结果
LevelComplete=AllComplete=1; //退出
} } } }
void Test( ) { if ((x==TargetX)&&(y==TargetY)) //已到目标
{ for (int i=0;i<=Level;i++) cout<<(int)Act[i]; //输出结果
cout<<endl; cout<<Level+1<<" "<<sum1<<" "<<sum2<<endl; LevelComplete=AllComplete=1; //完成搜索
} }
int ActOK( ) { int tx=x+dx[Act[Level]-1]; //将到点的x坐标
int ty=y+dy[Act[Level]-1]; //将到点的y坐标
if (Act[Level]>MaxAct) //方向错误?
return 0; if ((tx>=SX)||(tx<0)) //x坐标出界?
return 0; if ((ty>=SY)||(ty<0)) //y坐标出界?
return 0; if (Table[ty][tx]==1) //已到过?
return 0; if (Block[ty][tx]==1) //有障碍?
return 0; x=tx; y=ty; //移动
Table[y][x]=1; //做已到过标记
return 1; }
void Back( ) { x-=dx[Act[Level-1]-1]; y-=dy[Act[Level-1]-1]; //退回原来的点
Table[y][x]=0; //清除已到过标记
Act[Level]=0; //清除方向
Level--; //回上一层
}
int GetNextAct( ) //找到下一个移动方向。这一段程序有些乱,
//仔细看!
{ int dis[4]; int order[4]; int t=32767; int tt=2; for (int i=0;i<4;i++) dis[i]=abs(x+dx[i]-TargetX)+abs(y+dy[i]-TargetY); for (i=0;i<4;i++) if (dis[i]<t) { order[0]=i+1; t=dis[i]; } if (Act[Level]==0) return order[0]; order[1]=-1; for (i=0;i<4;i++) if ((dis[i]==t)&&(i!=(order[0]-1))) { order[1]=i+1; break; } if (order[1]!=-1) { for (i=0;i<4;i++) if (dis[i]!=t) { order[tt]=i+1; tt++; } } else { for (i=0;i<4;i++) if (dis[i]!=t) { order[tt-1]=i+1; tt++; } }
if (Act[Level]==order[0]) return order[1]; if (Act[Level]==order[1]) return order[2]; if (Act[Level]==order[2]) return order[3]; if (Act[Level]==order[3]) return 5; }
| |