度优先搜索(DFS)是一个递归过程,有回退过程。
下面是一道OJ上的题目,借此来实现下DFS~
题目来源:
Zhejiang Provincial Programming Contest 2004,ZOJ2110
题目描述:
一只小狗在一个古老的迷宫里找到一根骨头,当它叼起骨头时,迷宫开始颤抖,它感觉到地面开始下沉。它才明白骨头是一个陷阱,它拼命地试着逃出迷宫。
迷宫是一个N×M 大小的长方形,迷宫有一个门。刚开始门是关着的,并且这个门会在第T 秒
钟开启,门只会开启很短的时间(少于一秒),因此小狗必须恰好在第T 秒达到门的位置。每秒钟,
它可以向上、下、左或右移动一步到相邻的方格中。但一旦它移动到相邻的方格,这个方格开始
下沉,而且会在下一秒消失。所以,它不能在一个方格中停留超过一秒,也不能回到经过的方格。
小狗能成功逃离吗?请你帮助他。
输入描述:
输入文件包括多个测试数据。每个测试数据的第一行为三个整数:N M T,(1<N, M<7;
0<T<50),分别代表迷宫的长和宽,以及迷宫的门会在第T 秒时刻开启。
接下来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<iostream>
- #include<cmath>
- 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;
- }
运行结果:
Ps:如有bug,欢迎拍砖~