POJ_3669 Meteor Shower(BFS)

题目请点我
题解:
这道题涉及到状态转换,所以放入到队列里广搜是没错的。最开始的思路是设定一个时间轴,按照每刻能走到的地方去扩展,按照炸弹的爆炸去排除一些点。这种思路是可以过得,但是可能稍微麻烦了一点,其实可以换一种思路,在最开始标记出所有会被炸到的点,然后可以对不会再扩展的点直接进行判断,而可以扩展的点一样拓展,可能会快一点。觉得自己的方法是笨了一点,可能会很浪费时间,而且会感觉很乱。
另外有两点需要注意的地方:
1.使用scanf,printf输入输出,否则TLE;
2.注意可能会还没动就挂了,时间轴从0开始。
3.看网上说会有边界问题,开大点总没有错。
测试数据:

2
0 1 1
1 0 1
-1
1
0 0 0
-1
1
0 2 5
0

代码实现:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#define MAX_M 50010
#define MAX_P 500
#define INF 0x7fffffff

using namespace std;

struct stage{
    int x,y;
    int time;
};
struct meteor{
    int x,y,t;
    friend bool operator < (meteor a,meteor b){
        return a.t < b.t;
    }
};
int M;
int snum;
int Etime;
int result;
meteor ms[MAX_M];
queue<stage> Q;
int maze[MAX_P][MAX_P];
int show[MAX_P][MAX_P];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
void bfs();
int main()
{
    while( scanf("%d",&M) != EOF ){
        for( int i = 0; i < M; i++ ){
            scanf("%d%d%d",&ms[i].x,&ms[i].y,&ms[i].t);
        }
        sort(ms,ms+M);
        Etime = ms[M-1].t;
        bfs();
        printf("%d\n",result);
    }
    return 0;
}

void bfs(){
    snum = 1;
    stage bin;
    bin.x = 0;
    bin.y = 0;
    bin.time = 0;
    Q.push(bin);
    int pos = 0;
    result = INF;
    memset(show,0,sizeof(show));
    memset(maze,0,sizeof(maze));
    show[0][0] = 1;
    for( int i = 0; i <= Etime+1; i++ ){
        int add = 0;
        for( int j = 0; j < snum; j++ ){
            stage tmp = Q.front();
            Q.pop();
            if( maze[tmp.x][tmp.y] == 1 ){
                add--;
                continue;
            }
            if( tmp.time != i-1 ){
                Q.push(tmp);
                continue;
            }
            Q.push(tmp);
            for( int k = 0; k < 4; k++ ){
                int nx = tmp.x+dx[k];
                int ny = tmp.y+dy[k];
                if( nx>=0 && ny>=0 && show[nx][ny] != 1 ){
                    add++;
                    stage next;
                    next.x = nx;
                    next.y = ny;
                    next.time = tmp.time+1;
                    Q.push(next);
                    show[nx][ny] = 1;
                }
            }
        }
        snum = snum+add;
        if( snum == 0 ){
            result = -1;
            break;
        }
        while( pos < M && ms[pos].t == i ){
            int x,y;
            x = ms[pos].x;
            y = ms[pos].y;
            maze[x][y] = 1;
            for( int k = 0; k < 4; k++ ){
                int nx = x+dx[k];
                int ny = y+dy[k];
                if( nx>=0 && ny>=0 ){
                    maze[nx][ny] = 1;
                }
            }
            pos++;
        }
    }
    if( result != INF ){
        return ;
    }
    while( !Q.empty() ){
        stage tmp;
        tmp = Q.front();
        Q.pop();
        result = min(result,tmp.time);
    }
    return ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值