CSU - 2031 Barareh on Fire(BFS 预处理)

这个题很久以前就看到过,一直觉得好麻烦不想写,今天终于下定决心……花了两个多小时,总算是理解了。

题目戳我

题目大意:

    给你一个NxM的方格,有一些格子已经着火了,一个人在s处,如果他能跑到t除就可以成功获救。人只能向东、西、南、北四个方向跑,而火经过时间t就会向东、西、南、北、东北、西北、东南、西南八个方向蔓延,使相邻的八个格子都着火,并且一旦着火,火就不会熄灭。问你最少经过多久这个人能获救,如果不能获救就输出Impossible。

题目思路:

  这个题目需要一下预处理,先把每个格子着火的时间算出,这样就跟最基本的bfs一样了,入对的时候判断一下此时火是不是已经烧过来了就好了~

题目代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 105

using namespace std;
int dx[8]={1,1,0,-1,-1,-1,0,1};//火的八个方向
int dy[8]={0,-1,-1,-1,0,1,1,1};
int ddx[4]={1,0,-1,0};//人的四个方向
int ddy[4]={0,-1,0,1};
int vis[maxn][maxn];
int tim[maxn][maxn];
struct COO
{
     int x,y;
     int mit;
}start,mid,nxt;
int fx,fy,tx,ty;
int n,m,k;

queue<COO>q;

int bfs()//bfs模板
{
     //memset(vis,0,sizeof(vis));
     while(!q.empty())
     {
          q.pop();
     }
     //
     start.x=fx;
     start.y=fy;
     vis[fx][fy]=1;
     start.mit=0;
     q.push(start);
     while(!q.empty())
     {
          //printf("mm\n");
          mid=q.front();
          q.pop();
          if(mid.x==tx&&mid.y==ty&&mid.mit<tim[tx][ty])
          {
               return mid.mit;
          }
          for(int i=0;i<4;i++)
          {
               int nx=mid.x+ddx[i];
               int ny=mid.y+ddy[i];
               if(nx>=0&&nx<n&&ny>=0&&ny<m&&!vis[nx][ny]&&(mid.mit+1)<tim[nx][ny])
               {
                    //printf("ff\n");
                    nxt.mit=mid.mit+1;
                    nxt.x=nx;
                    nxt.y=ny;
                    vis[nx][ny]=1;
                    q.push(nxt);
               }
          }
     }
     return -1;
}
int main(void)
{

     char ch[maxn][maxn];
     while(~scanf("%d%d%d",&n,&m,&k)&&(n+m+k))
     {
          memset(tim,0x3f3f,sizeof(tim));

          while(!q.empty())
          {
               q.pop();
          }
          //初始化
          for(int i=0;i<n;i++)
          {
               scanf("%s",ch[i]);
          }
          for(int i=0;i<n;i++)
          {
               for(int j=0;j<m;j++)
               {
                    if(ch[i][j]=='f')
                    {
                         tim[i][j]=0;
                         start.x=i;
                         start.y=j;
                         start.mit=0;
                         q.push(start);
                    }
                    if(ch[i][j]=='s')
                    {
                         fx=i;fy=j;
                    }
                    if(ch[i][j]=='t')
                    {
                         tx=i;ty=j;
                    }
               }
          }
          //输入
          while(!q.empty())
          {
               //printf("mm\n");
               mid=q.front();
               q.pop();
               for(int i=0;i<8;i++)
               {
                    int nx=mid.x+dx[i];
                    int ny=mid.y+dy[i];
                    nxt.x=nx;
                    nxt.y=ny;
                    if(nx>=0&&nx<n&&ny>=0&&ny<m)
                    {
                         nxt.x=nx;
                         nxt.y=ny;
                         nxt.mit=mid.mit+k;
                         //tim[nx][ny]=mid.mit+k;
                         if(nxt.mit<tim[nx][ny])//如果发现更早的时间就不断更新tim数组
                         {
                              tim[nx][ny]=nxt.mit;
                              q.push(nxt);//把该点再次入队,因为这时之前根据这个点扩散出去的都要重新算了
                         }
                    }
               }
          }
          //预处理,留下的要用的是tim数组,所以可以用上面定义的队列和变量不用再定义有一个
          memset(vis,0,sizeof(vis));
          int ans=bfs();
          //printf("%d-------------\n",ans);
          if(ans==-1)
               printf("Impossible\n");
          else
               printf("%d\n",ans);
     }
     return 0;
}

呼呼

猜你喜欢

转载自blog.csdn.net/destiny1507/article/details/81289672