您的位置:首页 > 其它

POJ 3669 Meteor Shower(BFS)

2016-07-22 11:35 381 查看
题目:

Meteor Shower

Time Limit: 1000MS Memory Limit: 65536K

Total Submissions: 15145 Accepted: 3985

Description

Bessie hears that an extraordinary meteor shower is coming; reports say that these meteors will crash into earth and destroy anything they hit. Anxious for her safety, she vows to find her way to a safe location (one that is never destroyed by a meteor) . She is currently grazing at the origin in the coordinate plane and wants to move to a new, safer location while avoiding being destroyed by meteors along her way.

The reports say that M meteors (1 ≤ M ≤ 50,000) will strike, with meteor i will striking point (Xi, Yi) (0 ≤ Xi ≤ 300; 0 ≤ Yi ≤ 300) at time Ti (0 ≤ Ti ≤ 1,000). Each meteor destroys the point that it strikes and also the four rectilinearly adjacent lattice points.

Bessie leaves the origin at time 0 and can travel in the first quadrant and parallel to the axes at the rate of one distance unit per second to any of the (often 4) adjacent rectilinear points that are not yet destroyed by a meteor. She cannot be located on a point at any time greater than or equal to the time it is destroyed).

Determine the minimum time it takes Bessie to get to a safe place.

Input

Line 1: A single integer: M

Lines 2..M+1: Line i+1 contains three space-separated integers: Xi, Yi, and Ti

Output

Line 1: The minimum time it takes Bessie to get to a safe place or -1 if it is impossible.

Sample Input

4

0 0 2

2 1 2

1 1 2

0 3 5

Sample Output

5

Source

USACO 2008 February Silver

输入:

有m个流星,接下来的m行,每行前两个数代表攻击的点的坐标,第三个数代表攻击的时间。

注意理解这句话:She cannot be located on a point at any time greater than or equal to the time it is destroyed).他不能在一个已经被攻击了的或者正在被攻击的点。

题意:

有m个流星攻击第一象限(0<=x<=300 && 0<=y<=300)这个范围内的点,并且,陨石在攻击某个点的同时,会将这个点的上下左右4个点一起攻击。在(0, 0)这个点第0分钟时有一个人,他只能上下左右的走一个单位长度, 花费一个单位时间。问他能否逃过m个流星的攻击,能则输出最短时间,不能输出-1

思路:

思路很简单,BFS,模拟上下左右的操作。首先预处理一下被攻击的点,以及它上下左右4个点都被攻击,如果BFS走到了没有被攻击的点,那就成功,否则失败。有一点值得注意,预处理后,如果(0, 0)这个点没有被攻击,那么不需要走。如果这个点一开始就被攻击,gameover。

总结:

这题MLE了我好多发。。。对BFS的理解还是很浅,还是和我写的第一发BFS时遇到的那个问题一样,此题中已经走过的点就不要再走,如何理解呢,在该点被走过后,说明该点还未被攻击,并且从该点出发的四个操作已经入队了,如果再回到该点,又会重复上下左右四个操作,重复走某个点肯定会导致时间增加,并不是最短。

那么,我们不禁想,是不是某次必须重复走某个点才能够躲避流星攻击呢?这是不可能的,点已经被处理了,要么该点被攻击,要么不被攻击,我们的目标是找到一个不被攻击的点,一个已经被走过的点,我们不停在这,说明这个点之后要被攻击那么这个点可以不用再访问了,所有的在边界范围内的点都能遍历到,为何要重新走这个点,我们要找一个不被攻击的点, 每个点都是稳定的状态如果我们找不到不被攻击的点,那么gameover

感觉越说越不清楚,哎。。

坑点:

明明说了边界为0<=x<=300 && 0<=y<=300我这样写WA了, 改大了一点判断边界,居然,居然过了,

exo me???(ps: 我的数组足够大,把判断条件改成0<=x<310 && 0<=y<310就过了)

代码:

#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#include <algorithm>

using namespace std;

struct node
{
int x, y, t;
};

int tag[310][310];
bool vis[310][310];
const int dx[5] = {1, -1, 0, 0, 0};
const int dy[5] = {0, 0, -1, 1, 0};

void bfs(){
if(tag[0][0] == 0x3f3f3f3f) {cout<<0<<endl; return;}
if(tag[0][0] == 0) {cout<<-1<<endl; return;}
queue<node> q;
q.push(node{0, 0, 0});
vis[0][0] = true;
while(!q.empty()){
node tmp = q.front(); q.pop();
if(tag[tmp.x][tmp.y]==0x3f3f3f3f) {cout<<tmp.t<<endl; return;}
for(int i=0; i<4; i++){
int now_x = tmp.x + dx[i];
int now_y = tmp.y + dy[i];
if(0<=now_x && now_x<310 && 0<=now_y && now_y<310
&& !vis[now_x][now_y] && tmp.t+1 < tag[now_x][now_y]){
q.push(node{now_x, now_y, tmp.t+1});
vis[now_x][now_y] = true;
}
}
}
cout<<-1<<endl;
return;
}

int main(){
int m, x, y, t;
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
cin>>m;
memset(tag, 0x3f, sizeof(tag));
memset(vis, false, sizeof(vis));

for(int i=0; i<m; i++){
scanf("%d %d %d", &x, &y, &t);
for(int j=0; j<5; j++){
int now_x = x + dx[j];
int now_y = y + dy[j];
if(0<=now_x && now_x<=300 &&300>=now_y && now_y>=0){
if(tag[now_x][now_y]==0x3f3f3f3f)
tag[now_x][now_y] = t;
else
tag[now_x][now_y] = min(tag[now_x][now_y], t);
}
}
}

bfs();

return 0;
}


最后,cin, cout一时爽,提交要超时!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: