实现DFS之“骨头的诱惑”

深度优先搜索(DFS)是一个递归过程,有回退过程。

下面是一道OJ上的题目,借此来实现下DFS~


题目来源:

Zhejiang Provincial Programming Contest 2004,ZOJ2110

题目描述:

一只小狗在一个古老的迷宫里找到一根骨头,当它叼起骨头时,迷宫开始颤抖,它感觉到地
面开始下沉。它才明白骨头是一个陷阱,它拼命地试着逃出迷宫。
迷宫是一个N×M 大小的长方形,迷宫有一个门。刚开始门是关着的,并且这个门会在第T 秒
钟开启,门只会开启很短的时间(少于一秒),因此小狗必须恰好在第T 秒达到门的位置。每秒钟,
它可以向上、下、左或右移动一步到相邻的方格中。但一旦它移动到相邻的方格,这个方格开始
下沉,而且会在下一秒消失。所以,它不能在一个方格中停留超过一秒,也不能回到经过的方格。
小狗能成功逃离吗?请你帮助他。
输入描述:
输入文件包括多个测试数据。每个测试数据的第一行为三个整数:N M T,(1
0
接下来N 行信息给出了迷宫的格局,每行有M 个字符,这些字符可能为如下值之一:
X: 墙壁,小狗不能进入 S: 小狗所处的位置
D: 迷宫的门 . : 空的方格
输入数据以三个0 表示输入数据结束。
输出描述:

对每个测试数据,如果小狗能成功逃离,则输出"YES",否则输出"NO"。

样例输入:

3 4 5

S...

.X.X

...D

4 4 8

.X.X

..S.

....

DX.X

4 4 5

S.X.

..X.

..XD

....

0 0 0

样例输出:

YES

YES

NO


下面贴上代码+注释~

Code:

#include
#include
using namespace std;

char map[9][9];	//地图
int n, m, t;	//迷宫的大小及门开启的时间
int dir[4][2] = { {0, -1}, {0, 1}, {-1, 0}, {1, 0} };	//4个方向
bool escape;	//记录是否逃脱标志

void dfs(int si, int sj, int di, int dj, int cnt)	//cnt为所用时间
{
	if(si>n || sj>m || si<=0 || sj<=0) return;	//越界
	if(si == di && sj == dj && cnt == t)		//临界条件,在t时刻时走到出口~
	{
		escape = 1;
		return;
	}
	//剪枝(temp不能小于0且不能为奇数)
	int temp = t-cnt - abs(si-di) - abs(sj-dj);
	if(temp<0 || temp%2) return;
	//DFS遍历
	for(int i = 0; i < 4; i++) if(map[si+dir[i][0]][sj+dir[i][1]] != 'X')
	{
		map[si+dir[i][0]][sj+dir[i][1]] = 'X';		//将走过的地方设为墙壁
		dfs(si+dir[i][0], sj+dir[i][1], di, dj, cnt+1);
		if(escape) return;				//当找到出口时,返回即可
		map[si+dir[i][0]][sj+dir[i][1]] = '.';		//回退,恢复为可走点
	}
	return;
}

int main()
{
	int si, sj;		//小狗所在位置
	int di, dj;		//出口所在位置
	while(scanf("%d%d%d", &n, &m, &t))	//输入迷宫的长n、宽m、及出口处门开的时刻t
	{
		int wall = 0;	//墙壁的数量,便于剪枝
		getchar();	//屏蔽scanf后的转行符的影响
		if(n == 0 && m == 0 && t == 0) break;	//当输入"0 0 0"时结束
		//确定小狗坐标、出口坐标、墙壁的数量
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= m; j++)
			{
				scanf("%c", &map[i][j]);
				if(map[i][j] == 'S') { si = i; sj = j; }
				else if(map[i][j] == 'D') { di = i; dj = j; }
				else if(map[i][j] == 'X') wall++;
			}
			getchar();	//作用同上
		}	
		
		if(n*m <= t+wall) { printf("NO\n"); continue; }	//剪枝

		escape = 0;
		map[si][sj] = 'X';
	
		dfs(si, sj, di, dj, 0);
	
		if(escape) printf("YES\n");		
		else printf("NO\n");
	}
	return 0;
}

运行结果:

实现DFS之“骨头的诱惑”_第1张图片

Ps:如有bug,欢迎拍砖~

你可能感兴趣的:(狂奔のC/C++,狂奔の数据结构与算法,数据结构与算法随笔,C/C++每日小练)