Tempter of the Bone HDU - 1010 DFS剪枝

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值