Tempter of the Bone HDU - 1010
小狗在一个古老的迷宫里发现了一块骨头,这让它很着迷。然而,当它捡起这块骨头时,迷宫开始摇晃,小狗可以感觉到地面在下沉。他意识到那块骨头是个陷阱,于是拼命地想走出迷宫。
迷宫是一个长方形的,大小为N×m。迷宫里有一扇门。在开始的时候,门是关闭的,它会在第t秒打开一小段时间(不到1秒)。因此,小狗必须在第t秒准时到达门口。在每一秒钟,他可以移动一个街区到一个上,下,左和右相邻的街区。一旦他进入一个街区,这个街区的地面就会在接下来的一秒钟开始下沉消失。他不能在一个街区停留超过一秒钟,也不能搬到一个参观过的街区。可怜的小狗能活下来吗?请帮助他。
(以上来自有道翻译)
Input
The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:
‘X’: a block of wall, which the doggie cannot enter;
‘S’: the start point of the doggie;
‘D’: the Door; or
‘.’: an empty block.
The input is terminated with three 0’s. This test case is not to be processed.
Output
For each test case, print in one line “YES” if the doggie can survive, or “NO” otherwise.
Sample Input
4 4 5
S.X.
…X.
…XD
…
3 4 5
S.X.
…X.
…D
0 0 0
分析:
开始没看清题意,用了BFS,结果当然是不对的,因为只有当步数step恰好等于T值的时候才能输出YES。然后用了DFS,结果超时,看discuss,知道了这个题需要剪枝。
剪枝的方法:算出起点到终点的最短路径dist = abs(startr-endr)+abs(startc-endc);
如果这个值比T大,或者比T小但是T-dist为奇数,那么就是NO,具体原因可以参见博客(【HDU - 1010】Tempter of the Bone(dfs+剪枝))
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 10;
char G[maxn][maxn];
int vis[maxn][maxn];
int N, M, T;
int ok;
const int rpls[] = { -1,0,1,0 };
const int cpls[] = { 0,-1,0,1 };
bool judge(int x, int y) { return x >= 0 && x < N && y >= 0 && y < M; }
void dfs(int r, int c, int step) {
if (G[r][c] == 'D' && step == T)ok = true;
if (step > T || ok)return;
vis[r][c] = 1;
for (int i = 0;i < 4;i++) {
int x = r + rpls[i], y = c + cpls[i];
if (judge(x, y) && !vis[x][y] && G[x][y] != 'X') {
dfs(x, y, step + 1);
}
}
vis[r][c] = 0;
}
int main() {
while (scanf("%d%d%d", &N, &M, &T) == 3 && N && M && T) {
int startr, startc;
int endr, endc;
for (int i = 0;i < N;i++) {
char s[10];scanf("%s", s);
for (int j = 0;j < M;j++) {
G[i][j] = s[j];
if (s[j] == 'S') { startr = i;startc = j; }
else if (s[j] == 'D') { endr = i;endc = j; }
}
}
int dist = abs(startr - endr) + abs(startc - endc);
if (T < dist || (T - dist) % 2) { printf("NO\n");continue; }
ok = false;
memset(vis, 0, sizeof(vis));
dfs(startr, startc, 0);
printf("%s\n", ok ? "YES" : "NO");
}
return 0;
}