题解 JZOJ 1350.流星雨(meteor)

题目描述:

贝茜听说了一个骇人听闻的消息:一场流星雨即将袭击整个农场,由于流星体积过大,它们无法在撞击到地面前燃烧殆尽,届时将会对它撞到的一切东西造成毁灭性的打击。很自然地,贝茜开始担心自己的安全问题。以FJ牧场中最聪明的奶牛的名誉起誓,她一定要在被流星砸到前,到达一个安全的地方(也就是说,一块不会被任何流星砸到的土地)。如果将牧场放入一个直角坐标系中,贝茜现在的位置是原点,并且,贝茜不能踏上一块被流星砸过的土地。

根据预报,一共有M颗流星(1 <= M <= 50,000)会坠落在农场上,其中第i颗流星会在时刻T_i (0 <= T_i <= 1,000)砸在坐标为(X_i, Y_i) (0 <= X_i <= 300;0 <= Y_i <= 300)的格子里。流星的力量会将它所在的格子,以及周围4个相邻的格子都化为焦土,当然贝茜也无法再在这些格子上行走。

贝茜在时刻0开始行动,它只能在第一象限中,平行于坐标轴行动,每1个时刻中,她能移动到相邻的(一般是4个)格子中的任意一个,当然目标格子要没有被烧焦才行。如果一个格子在时刻t被流星撞击或烧焦,那么贝茜只能在t之前的时刻在这个格子里出现。

请你计算一下,贝茜最少需要多少时间才能到达一个安全的格子。

输入:

第1行: 1个正整数:M

第2…M+1行: 第i+1行为3个用空格隔开的整数:X_i,Y_i,以及T_i

输出:

第1行: 输出1个整数,即贝茜逃生所花的最少时间。如果贝茜无论如何都无法 在流星雨中存活下来,输出-1。

思路:

设定 v i s [ i , j ] vis[i,j] vis[i,j]表示坐标为 ( i , j ) (i,j) (i,j)的安全范围。即过了时刻 v i s [ i , j ] vis[i,j] vis[i,j]坐标为 ( i , j ) (i,j) (i,j)的点就不能再走了。
注意当点 ( i , j ) (i,j) (i,j)为安全点时, v i s [ i , j ] = i n f vis[i,j]=inf vis[i,j]=inf
于是我们就可以从原点进行广搜,记录这个点的步数,跑到一个安全点时就返回。若广搜结束还未返回,则无法逃离。
代码如下:

#include 
#include 
#include 
#include 

using namespace std;
const int N = 305;
const int inf = 0x3f3f3f3f;
const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, 1, -1};
int m, vis[N][N];
bool mark[N][N];
struct point {
	int x, y, step;
};

int read() {
	int x = 0; char ch = getchar();
	while(ch < '0' || ch > '9') ch = getchar();
	while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
	return x;
}
int bfs(int Sx, int Sy) {
	queue<point> q;
	q.push((point){Sx, Sy, 0});
	mark[Sx][Sy] = 1;
	if(vis[Sx][Sy] == 0)
		return -1;
	if(vis[Sx][Sy] == inf)
		return 0;
	while(!q.empty()) {
		point top = q.front();
		q.pop();
		if(vis[top.x][top.y] == inf) return top.step;
		for(int k = 0; k < 4; k++) {
			point next;
			next.x = top.x + dx[k];
			next.y = top.y + dy[k];
			next.step = top.step + 1;
			if(next.x >= 0 && next.y >= 0 && next.x <= 305 && next.y <= 305 && vis[next.x][next.y] > next.step && !mark[next.x][next.y]) {
				mark[next.x][next.y] = 1;
				q.push(next);
			}
		}
	}
	return -1;
}
int main()
{
	freopen("meteor.in", "r", stdin);
	freopen("meteor.out", "w", stdout);
	memset(vis, inf, sizeof vis);
//	printf("%d\n%d\n",inf, vis[0][0]);
	m = read();
	for(int i = 1; i <= m; i++) {
		int x = read(), y = read(), t = read();
		vis[x][y] = min(vis[x][y], t);
		for(int k = 0; k < 4; k++) {
			if(x + dx[k] >= 0 && y + dy[k] >= 0 && x + dx[k] <= 305 && x + dx[k] <= 305)
				vis[x + dx[k]][y + dy[k]] = min(vis[x + dx[k]][y + dy[k]], t);
		}
	}
	printf("%d", bfs(0, 0));
	fclose(stdin);
	fclose(stdout);
	return 0;
}

你可能感兴趣的:(广度优先搜索算法)