Rescue(DFS+回溯)

题目连接: Rescue

题目:

Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison.

Angel’s friends want to save Angel. Their task is: approach Angel. We assume that “approach Angel” is to get to the position where Angel stays. When there’s a guard in the grid, we must kill him (or her?) to move into the grid. We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too. And we are strong enough to kill all the guards.

You have to calculate the minimal time to approach Angel. (We can move only UP, DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.)

Input
First line contains two integers stand for N and M.
Then N lines follows, every line has M characters. “.” stands for road, “a” stands for Angel, and “r” stands for each of Angel’s friend.
Process to the end of the file.

Output
For each test case, your program should output a single integer, standing for the minimal time needed. If such a number does no exist, you should output a line containing “Poor ANGEL has to stay in the prison all his life.”

Sample Input
7 8
#.#####.
#.a#…r.
#…#x…
…#…#.#
#…##…
.#…

Sample Output
13

解题思路:

题目中这句==and “r” stands for each of Angel’s friend.==像我们暗示了可能Angel的朋友不止一个, 而对于这种显而易见的搜索题目而言, 我们选择单一起点跑多结果路线要比选多起点跑单一结果路线要舒服很多. 由于本题天使只有一个, 我们不妨从天使的角度出发, 看看她能否到达每一位朋友身边, 如果能, 那我们选出用时最少的.

AC代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 205
char a[MAXN][MAXN]; int m, n; /* 存图 */ int ans = 0x7fffffff; //结果
bool vis[MAXN][MAXN]; //用来标记是否已经到过这个点
int fx[][2] = { 1, 0, -1, 0, 0, 1, 0, -1 };
void dfs(int x, int y, int cou) //搜索, 当前所处 x行y列 已用时cou
{
	if (cou >= ans) return; //如果走当前这一步用时已经比结果要大了, 那就没必要在走下去了
	if (a[x][y] == 'r') { ans = cou; return; } //能到这一步, 说明此时的用时一定比ans要小, 所以更新结果
	for (int i = 0; i < 4; i++) {
		int dx = x + fx[i][0]; int dy = y + fx[i][1];
		if (dx < 1 || dy < 1 || dx > m || dy > n || vis[dx][dy] || a[dx][dy] == '#') continue;
		vis[dx][dy] = 1; //能到这一步, 一定是能跑到(dx, dy)的.
		if (a[dx][dy] == 'x') dfs(dx, dy, cou + 2); 
		else dfs(dx, dy, cou + 1);
		vis[dx][dy] = 0; //别忘了回溯
	}
}
int main(void)
{
	while (cin >> m >> n) {
		ans = 0x7fffffff; int x, y; //x, y存天使位置
		for (int i = 1; i <= m; i++) {
			scanf("%s", a[i] + 1); //这里不推荐%c一个个读, 首先由于空行要用getchar()函数抵消的问题, 我们并不能保证空格个数.
								   //其次, 由于scanf是一个函数, %c调用次数会很多, 其实效率不如%s快, 哪怕在经过一轮循环.
			for (int j = 1; j <= n; j++) if (a[i][j] == 'a') { x = i, y = j; }
		}
		dfs(x, y, 0);
		if (ans != 0x7fffffff) cout << ans << endl;
		else cout << "Poor ANGEL has to stay in the prison all his life." << endl;
	}
	return 0;
}

而对于本题而言, 给我们的经验总结就是, 对于起点复杂, 终点简单的搜索题而言, 将终点和起点互换有时不失为一种好方法.

关于%s和%c的问题我还是想多说几句, 我以前总感觉%c好, 因为读图判断也是要一个个字符判断是不是’a’字符, 那我为什么不%c去读呢. 直到有一个题, 我一直被T, 后来发现是%c的问题, 改成%s就过了, 当时我整个人差点原地爆炸.
在相同数据大小的情况下, 如果地图列数越多, 你越能发现%s的优势.
在计算时间花费时, 千万不要忘记了scanf是一个库函数, 而库函数的调用是很费时间的

END

发布了20 篇原创文章 · 获赞 0 · 访问量 513

猜你喜欢

转载自blog.csdn.net/weixin_45799835/article/details/104291074