深度优先遍历搜索迷宫路径

题目描述

输入迷宫的行列数(例如:10 10):5 5

输入迷宫的路径信息(0表示可以走,1表示不能走)

从左上到右下有路径则返回路径用*标识,找不到路径则提示不存在

例子1:

0 0 0 1 1

1 0 1 0 1

1 1 0 1 1

1 1 0 0 1

1 1 1 0 0

不存在一条迷宫路径!

例子2:

0 0 0 1 1

1 0 0 0 1

1 1 0 1 1

1 1 0 0 1

1 1 1 0 0

>>>有路径,直接输出<<<

* * * 1 1

1 0 * 0 1

1 1 * 1 1

1 1 * * 1

1 1 1 * *

解答实现

来处理深度优先搜索,代替递归函数,记录每个点的可达性以及其周围四个方向的可达性,

深度优先搜索不确保找到的是最短路径,完整代码:

#include <iostream>
#include <stack>
using namespace std;

// 用栈来模拟递归的dfs
// 定义迷宫每个节点的四个方向,从右开始,顺时针
const int RIGHT = 0;
const int DOWN = 1;
const int LEFT = 2;
const int UP = 3;

// 迷宫每个节点方向的数量
const int WAY_NUM = 4;

// 定义节点向某个方向行走是否可行
const int YES = 4;
const int NO = 5;

class Maze
{
public:
	Maze(int row, int col)
		: _row(row)
		, _col(col)
	{
		// 二维数组的创建
		_pMaze = new Node * [_row];
		for (int i = 0; i < _row; ++i)
		{
			_pMaze[i] = new Node[_col];
		}
	}

	// 初始化迷宫每个节点对象
	void initNode(int x, int y, int val)
	{
		_pMaze[x][y]._x = x;
		_pMaze[x][y]._y = y;
		_pMaze[x][y]._val = val;
		// 节点四个方向默认初始化
		for (int i = 0; i < WAY_NUM; ++i)
		{
			_pMaze[x][y]._state[i] = NO;
		}
	}
	// 初始化迷宫0节点的四个方向的可达性
	void setNodeState()
	{
		for (int i = 0; i < _row; ++i)
		{
			for (int j = 0; j < _row; ++j)
			{
				//cout << "(" << _pMaze[i][j]._x << "," << _pMaze[i][j]._y << ") ";
				// (i,j) 本身就不可达
				if (_pMaze[i][j]._val == 1)
				{
					continue; 
				}
				//(i, j) 四个方向的可达性设置
				// 右侧可达性
				if (j < _col - 1 && _pMaze[i][j + 1]._val == 0)
				{
					_pMaze[i][j]._state[RIGHT] = YES;
				}

				// 下方可达性
				if(i < _row - 1 && _pMaze[i + 1][j]._val == 0)
				{
					_pMaze[i][j]._state[DOWN] = YES;
				}

				if (j > 0 && _pMaze[i][j - 1]._val == 0)
				{
					_pMaze[i][j]._state[LEFT] = YES;
				}

				if (i > 0 && _pMaze[i - 1][j]._val == 0)
				{
					_pMaze[i][j]._state[UP] = YES;
				}
			}
			cout << endl;
		}
	}

	// 深度搜索路径
	void searchMazePath()
	{
		if (_pMaze[0][0]._val == 1)
		{
			return;
		}
		_stack.push(_pMaze[0][0]);

		while (!_stack.empty())
		{
			Node top = _stack.top();
			int x = top._x;
			int y = top._y;

			if (x == _row - 1 && y == _col - 1)
			{
				return;
			}

			// 往右寻找
			if (_pMaze[x][y]._state[RIGHT] == YES)
			{
				_pMaze[x][y]._state[RIGHT] = NO;
				// 防止再走回来
				_pMaze[x][y + 1]._state[LEFT] = NO;
				_stack.push(_pMaze[x][y + 1]);
				continue;
			}
			// 往下寻找
			if (_pMaze[x][y]._state[DOWN] == YES)
			{
				_pMaze[x][y]._state[DOWN] = NO;
				// 防止再走回来
				_pMaze[x + 1][y]._state[UP] = NO;
				_stack.push(_pMaze[x + 1][y]);
				continue;
			}
			// 往左寻找
			if (_pMaze[x][y]._state[LEFT] == YES)
			{
				_pMaze[x][y]._state[LEFT] = NO;
				// 防止再走回来
				_pMaze[x][y - 1]._state[RIGHT] = NO;
				_stack.push(_pMaze[x][y - 1]);
				continue;
			}
			// 往上寻找
			if (_pMaze[x][y]._state[UP] == YES)
			{
				_pMaze[x][y]._state[UP] = NO;
				// 防止再走回来
				_pMaze[x - 1][y]._state[DOWN] = NO;
				_stack.push(_pMaze[x - 1][y]);
				continue;
			}

			// 四个方向都无法走(可能是走过或者是值为1)
			_stack.pop();
		}
	}

	// 打印搜索结果
	void showMazePath()
	{
		if (_stack.empty())
		{
			cout << "不存在一条迷宫路径!" << endl;
		}
		else
		{
			while (!_stack.empty())
			{
				Node top = _stack.top();
				_pMaze[top._x][top._y]._val = '*';
				_stack.pop();
			}

			for (int i = 0; i < _row; ++i)
			{
				for (int j = 0; j < _col; ++j)
				{
					if (_pMaze[i][j]._val == '*')
					{
						cout << "* ";
					}
					else
					{
						cout << _pMaze[i][j]._val << " ";
					}
					
				}
				cout << endl;
			}
		}
	}
private:
	// 定义迷宫每个节点的信息
	struct Node
	{
		int _x;
		int _y;
		int _val;
		int _state[WAY_NUM]; // 往四个方向走的可行性
	};

	Node** _pMaze; // 二维数组存放迷宫
	int _row;
	int _col;
	stack<Node> _stack; // 用栈来代替递归进行深度搜索
};

int main()
{
	cout << "请输入迷宫的行列数(例如:10 10):"; 
	int row, col, data;
	cin >> row >> col;

	Maze maze(row, col); // 创建迷宫对象

	cout << "输入迷宫的每个位置信息(0表示可以走,1表示不能走):" << endl;
	for (int i = 0; i < row; ++i)
	{
		for (int j = 0; j < col; ++j)
		{
			cin >> data;
			maze.initNode(i, j, data);
		}
	}

	// 开始设置所有节点四个方向的状态
	maze.setNodeState();

	// 从左上角开始搜索路径
	maze.searchMazePath();

	// 打印迷宫路径搜索结果
	maze.showMazePath();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值