• poj3669 Meteor Shower


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

    在一个矩形区域,区域大小为0<=X<=300, 0<=Y<=300,有所谓流星坠落,给出M个流星坠落的时间和地点,问最少需要多少时间步能走到一个安全的格子上,从而不会遭受流星的撞击。每个流星坠落在某一格点后,其相邻四个格点会遭到破坏。

    样例输入

    4
    0 0 2
    2 1 2
    1 1 2
    0 3 5

    样例输出

    5

    思路

    • 假如起点(0,0)不会遭受到流星的攻击(也不会因为周围格子被攻击而延伸至它),那么也就不用移动就能保证安全。如果起点会受到攻击,不论是何时,我们都需要离开起点,那么哪里才是安全的终点呢?只要这个点上不会在有流星的攻击,这个点就是安全的终点,我们bfs出第一个安全的终点就是最少的时间步。
    • 根据输入我们可以标记每个受流星攻击的网格的时间,注意如果一个网格有多次被流星摧毁的时间,那么取最小的作为这个网格的摧毁时间,同时需要将这个网格上下左右四个网格也“以最近摧毁”原则更新被摧毁的时间。

    代码

    #include <iostream>
    #include <memory.h>
    #include <queue>
    #include <utility>
    using namespace std;
    typedef pair<int, int> PII;
    
    const int N = 302;
    int dx[] = {0, 1, 0, -1};
    int dy[] = {-1, 0, 1, 0};
    int time[N][N];
    int g[N][N];
    int bfs(){
        time[0][0] = 0;
        if(time[0][0] >=  g[0][0]) return -1;   //如果起点在时间0就被炸了, 那么直接失败...
        if(g[0][0] == 0x3f3f3f3f) return 0;     //如果起点不会被炸, 那么就不用走了...
        queue<PII> q;                           
        q.push(make_pair(0, 0));
        int time_step = 0;
        while(!q.empty()){
            PII p = q.front(); q.pop();
            for(int i = 0; i < 4; ++i){
                int x = p.first + dx[i], y = p.second + dy[i];
                if(x >= 0 && x <= N && y >= 0 && y <= N){
                    if(time[x][y] == -1){    //这个网格没有被访问过(不能走回头路)
                        time[x][y] = time[p.first][p.second] + 1;
                        if(g[x][y] == 0x3f3f3f3f){    //到达"终点"
                            return time[x][y];
                        }
                        if(time[x][y] < g[x][y] && g[x][y] != 0x3f3f3f3f) q.push(make_pair(x, y)); //如果这个网格要被炸但目前是安全的, 那么放入队列中
                    }
                }
            }
        }
        return -1;
    }
    
    int main(){
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        int M; scanf("%d", &M);
        memset(g, 0x3f, sizeof(g));      //g记录网格被摧毁的时间T, 初始为正无穷(0x3f3f3f3f), 表示不会被摧毁
        memset(time, -1, sizeof(time));  //time记录到某一网格的时间步数,-1表示未访问
        while(M--){
            int x, y, t;
            scanf("%d%d%d", &x, &y, &t);
            if(g[x][y] > t) g[x][y] = t;
            for(int i = 0; i < 4; ++i){     //按"最近时间摧毁"原则记录每个网格被摧毁的时间
                int nx = x + dx[i], ny = y + dy[i];
                if(nx >= 0 && nx <= N && ny >= 0 && ny <= N){
                    if(g[nx][ny] > t)
                        g[nx][ny] = t;
                }
            }
        }
        printf("%d", bfs());
    }
    
  • 相关阅读:
    [转载]PhotoShop性能优化
    SVN常用命令
    [转载]SVN使用教程
    MyEclipse Java Build Path详解
    MyEclipse安装后需要进行的配置
    c#中base64加密解密
    C# MD5 加密
    C# http Post 方法
    EPF与Myeclipse 增强代码自动智能提示
    汉字代码手册
  • 原文地址:https://www.cnblogs.com/patrolli/p/12194415.html
Copyright © 2020-2023  润新知