四种算法是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; }