算法思维——深度优先搜索

以一道题目,作为介入点:

定义一个二维数组N*M(其中2<=N<=10;2<=M<=10),如5 × 5数组下所示: 


int maze[5][5] = {


        0, 1, 0, 0, 0,


        0, 1, 0, 1, 0,


        0, 0, 0, 0, 0,


        0, 1, 1, 1, 0,


        0, 0, 0, 1, 0,


};


它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。入口点为[0,0],既第一空格是可以走的路。

Input

一个N × M的二维数组,表示一个迷宫。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。

Output

左上角到右下角的最短路径,格式如样例所示。

Sample Input

0 1 0 0 0

0 1 0 1 0

0 0 0 0 0

0 1 1 1 0

0 0 0 1 0

Sample Output

(0, 0)

(1, 0)

(2, 0)

(2, 1)

(2, 2)

(2, 3)

(2, 4)

(3, 4)

(4, 4)
 

输入描述:

 
 

输入两个整数,分别表示二位数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。

输出描述:

 
 

左上角到右下角的最短路径,格式如样例所示。

示例1

输入

5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

输出

(0,0)
(1,0)
(2,0)
(2,1)
(2,2)
(2,3)
(2,4)
(3,4)
(4,4)
想必这种题目,大家都很熟悉,走迷宫!
让我们来整理下,怎么来进行迷宫的行走:
1.从左上角定点(0,0)开始,将起始点加入到栈S;
2.弹出栈S的顶层结点,判断是否已经到达终点(4,4);
3.未到达终点,取出他的相邻结点,条件:相邻的结点不为1(1代表墙),结点不越界,所以取出(1,0)加入栈Q;
4.关键点来了,如果取到一个相邻结点里面退出继续循环,则采用的是DFS,如果直到取完所有的相邻结点再继续循环则是BFS;
5.我们先采用DFS的方式,取完一个就继续循环,重复2的步骤;
看下源码:
 
     
#include "stdafx.h"
#include <iostream>
#include <stack>
using namespace std;

//这种迷宫题的难点在于,输出一条路径

typedef struct _Point
{
	int x;
	int y;
	_Point()
	{
		x = 0;
		y = 0;
	};
	_Point(const int& v_nx, const int& v_ny)
	{
		x = v_nx;
		y = v_ny;
	};
	bool operator==(const _Point& v_p)
	{
		if(x == v_p.x && y == v_p.y)
		{
			return true;
		}
		return false;
	}
}POINT, *PPOINT;

int main()
{
	int MyMap[10][10] = {0}; //地图
	int M, N = 0;
	int dir[4][2] = {{0, 1},{1, 0},{0, -1},{-1, 0}}; 
	while(cin >> N >> M) //N行M列
	{
		for(int i = 0; i < N; ++i)
		{
			for(int j = 0; j < M; ++j)
				cin >> MyMap[i][j];
		}

		int MyVisit[10][10] = {0}; //用数组标识是否已经访问过
		//设置起始点
		POINT pointStart;
		pointStart.x = 0;
		pointStart.y = 0;
		//设置终点
		POINT pointEnd;
		pointEnd.x = N - 1;
		pointEnd.y = M - 1;

		stack<POINT> Queue;
		bool bFind = false;
		//首先将起点加入队列
		Queue.push(pointStart);
		MyVisit[pointStart.x][pointStart.y] = 1;
		while(!Queue.empty())
		{
			//取出结点
			POINT pointCur = Queue.top();
			if(pointCur == pointEnd) //遍历到终点了
			{
				bFind = true;
				break;
			}
			//计算相邻节点
			for(int i = 0; i < 4; ++i)
			{
				POINT pointNext(pointCur.x + dir[i][0], pointCur.y + dir[i][1]);
				//判断这个Next节点是否有效:是否越界,是否不是一堵墙
				if(pointNext.x >= 0 && pointNext.y >= 0 &&
					pointNext.x < N && pointNext.y < M &&
					MyMap[pointNext.x][pointNext.y] == 0)
				{
					if(MyVisit[pointNext.x][pointNext.y] == 0)//判断节点是否访问过
					{
						Queue.push(pointNext);
						MyVisit[pointNext.x][pointNext.y] = 1;
						break; //找到一个立马去找下一个,采用深度优先搜索的方式
					}
				}
			}
			if(!bFind)
			{
				continue;
			}
			else //如果最终未找到,则弹出这个结点,查找上一个结点,以此类推
			{
				Queue.pop();
			}
		}
		if(!Queue.empty())
		{
			stack<POINT> tmp;
			while(!Queue.empty())
			{
				tmp.push(Queue.top());
				Queue.pop();
			}
			while(!tmp.empty())
			{
				cout << "(" << tmp.top().x << "," << tmp.top().y << ")" << endl;
				tmp.pop();
			}
		}
		else
		{
			cout << "No Find One Path!" << endl;
		}
	}
		
	return 0;
}

猜你喜欢

转载自blog.csdn.net/fzuim/article/details/76047927