POJ No 3669 Meteor Shower_BFS搜索

#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxn = 500;
const int INF = 50000000;
int M;
struct Meteor {
    int X, Y;
    int Time;      //Time_i
    Meteor(int X = 0, int Y = 0, int T = 0) :
        X(X), Y(Y), Time(T) {}
    bool operator < (const Meteor& b) {  // 升序排序
        return Time < b.Time;
    }
} meteor[50000 + 3];
int dir[5][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}, {0, 0}};
bool used[maxn][maxn];
int field[maxn][maxn];  //标记好每个位置被流星砸(以及扩散到)的时间
int last;
int ans;              

void input();
void solve();
bool check(int r, int c, int T);
int BFS(int r, int c, int T);

void input()
{
    memset(used, false, sizeof(used));
    for (int i = 0; i < maxn; i++) {
        for (int j = 0; j < maxn; j++) {
            field[i][j] = INF;
        }
    }
    scanf("%d", &M);
    for (int i = 0; i < M; i++) {
        scanf("%d%d%d", &meteor[i].X, &meteor[i].Y, &meteor[i].Time);
    }
    sort(meteor, meteor + M);    //按照时间升序排序
    last = meteor[M - 1].Time;   //最后被毁灭的时间 

    for (int i = 0; i < M; i++)         //M个火球
    {
        for (int j = 0; j < 5; j++) {   //5个方向
            int x = meteor[i].X + dir[j][0],
                y = meteor[i].Y + dir[j][1];
            if ( check(x, y, meteor[i].Time) ) {
                field[x][y] = meteor[i].Time;   //x,y位置和周围扩散位置,破坏的时间
            }
        }
    }
}

bool check(int r, int c, int T)
{
    return r >= 0 && c >= 0 && field[r][c] > T;
}

int BFS(int r, int c, int T)
{
    used[r][c] = true;         //从原点开始
    queue<Meteor> que;
    Meteor cur;
    cur.X = r, cur.Y = c, cur.Time = T;
    que.push(cur); //开始的位置,和时间

    while (!que.empty())
    {
        Meteor m = que.front(); que.pop();
        for (int i = 0; i < 4; i++) {   //遍历4个方向, 因为最后一个方向,是在原地
            cur = m;
            cur.X = m.X + dir[i][0],
            cur.Y = m.Y + dir[i][1];    //周围位置
            cur.Time++;                 //移到下个位置的时间
            //如果火球落到该位置的时间>当前人的时间,表示还有机会移动
            if (check(cur.X, cur.Y, cur.Time) && !used[cur.X][cur.Y]) {
                used[cur.X][cur.Y] = true;
                //说明当前位置时间永远不会被炸到
                //last是最后被炸到的时间
                if (field[cur.X][cur.Y] > last) {
                    return cur.Time;   //则返回当前到达安全的时间
                }
                que.push(cur);         //否则入队列
            }
        }
    }
    return -1;  //不存在安全位置
}

void solve()
{
    input();
    if (field[0][0] == 0) {  //原点就被毁灭, 反应时间为0
        printf("-1\n");
    }
    else {
        printf("%d\n", BFS(0, 0, 0));
    }
}

int main()
{
    solve();
    return 0;
}

分析:1. 还是经典的BFS问题,主要是要 对被摧毁的位置的时间进行记录(先升序处理)(以及波及到的位置进行时间标志).

   2. 人行打算走下一步的时候, 先判断是否时间允许,允许标志为访问过(允许的时候,需要当前位置时间是否已经超过了 最后被毁灭位置的时间,是则返回 到达该安全位置的时间)。不允许则添加到队列中。

题目链接: http://poj.org/problem?id=3669

参考了这篇博客: http://www.cnblogs.com/ZefengYao/p/5935161.html

时间: 2024-08-08 06:43:12

POJ No 3669 Meteor Shower_BFS搜索的相关文章

POJ 3669 Meteor Shower(流星雨)

POJ 3669 Meteor Shower(流星雨) Time Limit: 1000MS    Memory Limit: 65536K 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 sa

[ACM] poj 1088 滑雪 (记忆化搜索DFS)

求n*m网格内矩形的数目[ACM] poj 1088 滑雪 (记忆化搜索DFS),布布扣,bubuko.com

poj 3156 hash+记忆化搜索 期望dp

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n,m; #define N 32 #define mod 10007LL #define mod2 10000007 #define inf 0x3fffffff typedef long long ll; typedef double dd; int f[N]

POJ 3126 Prime Path 广度优先搜索 难度:0

http://poj.org/problem?id=3126 搜索的时候注意 1:首位不能有0 2:可以暂时有没有出现在目标数中的数字 #include <cstdio> #include <cstring> #include <queue> using namespace std; const int maxn=1e4+5; const int inf=0x7fffffff; bool prim[maxn]; void judge(){ prim[2]=true; f

POJ 2449 Remmarguts&#39; Date (A*搜索求K短路)

传送门 这是一道裸的K短路的问题,我们将会用A*解决. 我们设计估值函数h的时候可以像这样想.因为h(n) <= h*(n)而且要尽量接近h*(n),所以我们想到,可以求一个从目标节点到其余节点的最短路,这个一定是小于等于实际值的.然后就用A*从起点开始搜索,找到一个节点v,就使cnt[v]加1.当cnt[v] > k时就可以剪枝了,因为这一定不再K短路的路线上了.很好通过反证法得到证明.当目标节点被搜索到了第k次的时候就可以结束搜索了. 要注意这道题有一个很坑的地方,就是若给出的起点=终点,

POJ 4968 DP||记忆化搜索

给出N个人的平局分X 根据GPA规则计算可能的最高平均GPA和最低平均GPA 可以DP预处理出来所有结果  或者记忆化搜索 DP: #include "stdio.h" #include "string.h" int inf=100000000; double a[11][1100],b[11][1100]; double Max(double a,double b) { if (a<b) return b; else return a; } double M

POJ 3669 Meteor Shower 题解 《挑战程序设计竞赛》

题目链接: http://poj.org/problem?id=3669 题意: 这个同学发现流星雨要来了,会对地球造成伤害于是决定逃跑.N颗流星会不定时降落在坐标轴第一象限300*300内的点上.给出每颗流星降落的坐标和时刻,求这个同学能否成功逃跑,能的话用时多少. 思路: 略有一点tricky,无法变通了(@﹏@)~.看了码农场的代码. 这道题没有给出地图,所以需要自己生成地图. 关键的点在于:在生成地图的时候,将每个点的初始值设为无穷大(表示不会有流星),将要被摧毁的点设置为流星降落的时刻

POJ 3669 Meteor Shower【BFS】

POJ 3669 去看流星雨,不料流星掉下来会砸毁上下左右中五个点.每个流星掉下的位置和时间都不同,求能否活命,如果能活命,最短的逃跑时间是多少? 思路:对流星雨排序,然后将地图的每个点的值设为该点最早被炸毁的时间 #include <iostream> #include <algorithm> #include <queue> #include <cstring> using namespace std; #define INDEX_MAX 512 int

poj 3669 Meteor Shower

Meteor Shower Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16339   Accepted: 4293 Description Bessie hears that an extraordinary meteor shower is coming; reports say that these meteors will crash into earth and destroy anything they h