poj 3669 Meteor Shower

题意:流星雨来袭,为了找一个安全的地方,地图相当于平面坐标系第一象限,初始在原点。然后,每颗流星都会在某个时间砸下来,砸到的地方连同上下左右都会毁灭,此地方就不能通过了,他只能走其他地方。移动速度是每时刻移动一步,上下左右,不能对角线移动,求移到安全地点的最小移动速度。

思路:从原点开始搜索,如果当前点是安全的。不然的话向四个方向搜索,如果该方向的点没有搜索过,并且到达该点的时间小于那一点被破坏的时间减一,那么就认为该点是可以到达的,记录到达该点的时间,把该点入队。

搜索的之前的处理是这样的。把每个点都设置为安全(永远不会被破坏),该点被破坏的时间为INF。读入数据的时候,对每一个输入,我们对五个点(输入坐标的点和其上下左右的四个点)进行处理:该点会被破坏,每次取该点被破坏的最小时间。(因为一炸一大片,会有点重合,所以要取最小时间,)-----卡了我好久

#include<stdio.h>
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
#define maxn 400
const int n=305,INF=1012;
struct node
{
    int x,y;
    bool f;//会不会破坏
    int t;//被破坏最小时间
    int s;//走到这里需要的最小时间
}p[n][n];
bool isin(int x,int y)
{
    return x<=n&&x>=0&&y<=n&&y>=0;
}
int dx[5]={0,0,0,1,-1};
int dy[5]={0,1,-1,0,0};
int step;
bool vis[n][n];
queue<node> q;
node p1,p2;
void bfs()
{
    int i,j,k;
    while(!q.empty())
    {
        p1=q.front();
        q.pop();
        if(p1.f==0){step=p1.s;break;}
        for(k=1;k<5;k++)
        {
            i=p1.x+dx[k];
            j=p1.y+dy[k];
            if(!vis[i][j]&&isin(i,j))
            {
                if(p1.s+1<p[i][j].t)
                {
                    p[i][j].s=p1.s+1;
                    q.push(p[i][j]);
                    vis[i][j]=1;
                }

            }
        }
    }
}
int main()
{
   int m,i,x,y,t,j;
   while(scanf("%d",&m)!=EOF)
   {
       for(i=0;i<n;i++)
       {
           for(j=0;j<n;j++)
           {
               p[i][j].x=i;
               p[i][j].y=j;
               p[i][j].f=0;
               p[i][j].t=INF;
           }
       }
       for(i=0;i<m;i++)
       {
           scanf("%d%d%d",&x,&y,&t);
           for(j=0;j<5;j++)
           {
               int a=x+dx[j],b=y+dy[j];
               if(isin(a,b))
               {
                   p[a][b].f=1;//破坏了
                   p[a][b].t=min(p[a][b].t,t);
               }
           }
       }
       while(!q.empty())
        q.pop();
        p[0][0].s=0;
       q.push(p[0][0]);
       vis[0][0]=1;
       step=-1;
       memset(vis,0,sizeof(vis));
       bfs();
       printf("%d\n",step);
   }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值