您的位置:首页 > 其它

回溯法求迷宫

2017-10-02 09:08 295 查看
首先我们先“创建”一个迷宫,把其放在Mazemap.txt文件中。

0代表可以走的路,1表示不通的路。

首先定义一个结构体,用来存储坐标

template<size_t M, size_t N>
class Maze
{
public:
Maze(int maze[M]
)
{
for (size_t i = 0; i < M; ++i)
{
for (size_t j = 0; j < N; ++j)
{
_maze[i][j] = maze[i][j];
}
}
}

struct Pos
{
int _row; // 行
int _col; // 列
};


构造一个函数,判断可不可以走下去,其位置是否是0

bool CheckAccess(Pos next)
{
if ((next._row >= 0 && next._row < M)
&&(next._col >= 0 && next._col <= N)
&& _maze[next._row][next._col] == 0)
{
return true;
}

return false;
}


接下来求解

<非递归法>

bool GetMazePath(Pos entry)
{
stack<Pos> paths;
paths.push(entry);

while (!paths.empty())
{
// 栈顶的坐标就是当前位置
Pos cur = paths.top();
_maze[cur._row][cur._col] = 2;

// 已经到出口
if (cur._row == M-1)
{
return true;
}

// 试探四个方向
// 上
Pos next = cur;
next._row -= 1;
if(CheckAccess(next))
{
paths.push(next);
continue;
}

// 右
next = cur;
next._col += 1;
if(CheckAccess(next))
{
paths.push(next);
continue;
}

// 下
next = cur;
next._row += 1;
if(CheckAccess(next))
{
paths.push(next);
continue;
}

// 左
next = cur;
next._col -= 1;
if(CheckAccess(next))
{
paths.push(next);
continue;
}

Pos back = paths.top();
_maze[back._row][back._col] = 3;
paths.pop();
}

return false;
}


<递归法>

bool GetMazePathR(Pos entry)
{
Pos cur = entry;
_maze[cur._row][cur._col] = 2;
// 已经找到出口
if (entry._row == N-1)
{
return true;
}

Pos next = cur;

// 上
next._row -= 1;
if (CheckAccess(next))
{
// 子问题
if (GetMazePathR(next))
return true;
}

// 右
next = cur;
next._col += 1;
if (CheckAccess(next))
{
if (GetMazePathR(next))
return true;
}

// 下
next = cur;
next._row += 1;
if (CheckAccess(next))
{
if (GetMazePathR(next))
return true;
}

// 左
next = cur;
next._col -= 1;
if (CheckAccess(next))
{
if (GetMazePathR(next))
return true;
}

//
_maze[cu
4000
r._row][cur._col] = 3;
return false;
}


继续构建一个函数用来检测。

bool CheckAccess(Pos next, Pos cur)
{
if ((next._row >= 0 && next._row < M)
&&(next._col >= 0 && next._col <= N))
{
if (_maze[next._row][next._col] == 0)
{
return true;
}
else if (_maze[next._row][next._col] == 1)
{
return false;
}
else
{
return _maze[next._row][next._col] > _maze[cur._row][cur._col]+1;
}
}
else
{
return false;
}
}


接下来求最短路径

void GetShortPath(Pos entry,
stack<Pos>& path, stack<Pos>& shortPath)
{
Pos cur = entry;
path.push(cur);

// 已经找到出口
if (entry._row == N-1)
{
Print();
if (shortPath.empty() || path.size() < shortPath.size())
{
shortPath = path;
}
}

Pos next = cur;

// 上
next._row -= 1;
if (CheckAccess(next, cur))
{
// 子问题
_maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;
GetShortPath(next, path, shortPath);
}

// 右
next = cur;
next._col += 1;
if (CheckAccess(next, cur))
{
_maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;
GetShortPath(next, path, shortPath);
}

// 下
next = cur;
next._row += 1;
if (CheckAccess(next, cur))
{
_maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;
GetShortPath(next, path, shortPath);
}

// 左
next = cur;
next._col -= 1;
if (CheckAccess(next, cur))
{
_maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;
GetShortPath(next, path, shortPath);
}

path.pop();
}


其余代码如下

protected:
int _maze[M]
;
};

void ReadMaze(int maze[10][10])
{
FILE* fout = fopen("MazeMap.txt", "r");
assert(fout);

for (size_t i = 0; i < 10; ++i)
{
for (size_t j = 0; j < 10;)
{
char ch = fgetc(fout);
if (ch == '0' || ch == '1' || ch == '2')
{
maze[i][j] = ch - '0';
++j;
}
}
}
}

void TestMaze()
{
// 如何动态创建一个二维数组?
// 跟静态的二维数组的区别是什么?
// 迷宫的最优解--多条路径中最短的一条?
int maze[10][10];
ReadMaze(maze);

Maze<10, 10> m(maze);
Maze<10, 10>::Pos entry;
entry._row = 2;
entry._col = 0;
//m.GetMazePath(entry);
//cout<<m.GetMazePathR(entry)<<endl;

stack<Maze<10, 10>::Pos> path, shortPath;
m.GetShortPath(entry, path, shortPath);
//m.Print();
}


迷宫求解对于数据结构的学习有很大帮助,这段代码我花费了 一周多时间来编写和理解,刚开始有些点还是不是完全理解 ,经过每天多次思考测试,最后写出了。希望和我一样正在学习这部分的同学可以多多思考,温故而知新。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: