【算法】深度优先搜索

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

 

定义一个二维数组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; 
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值