2 条题解

  • 1
    @ 2026-3-6 16:57:59

    由于火可以蔓延到四周,人也可以前往四周(除了#的地方)所以我们可以在结构体中多加入状态p,表示当前扩散的是人还是火。注意到: 如果一个格子已经着火,或者在乔进入该格子的时刻恰好着火,则该格子对乔来说是危险的,乔不能进入该格子。 那么我们可以先扩散火 再走人 否则会因为特判问题头痛(其实是我不会写)详细见代码

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int r,c,sx,sy;//行列,开始的坐标
    char a[1010][1010];//地图
    int dx[]={-1,1,0,0};
    int dy[]={0,0,-1,1};//偏移
    struct grid{
        int x,y,p;//p=0时表示是人 p=1时表示火
    };
    int dis[1010][1010];//距离
    vector<grid>f;
    void bfs(int x,int y,int p){
        queue<grid>q;
        for(int i=0;i<f.size();i++){//先着火 把火全部入队
            int e=f[i].x,r=f[i].y,c=f[i].p;
            q.push({e,r,c});
        }
        q.push({x,y,p});
        dis[x][y]=0;//人再入队
        while(!q.empty()){
            int tx=q.front().x,ty=q.front().y,tp=q.front().p;
            q.pop();//拿到队首并出队
            if(tp==0){//人跑出去了
                if(tx==1||tx==r||ty==1||ty==c){
                    cout<<dis[tx][ty]+1;
                    return ;
                }
            }
            for(int i=0;i<4;i++){
                int nx=tx+dx[i],ny=ty+dy[i],np=tp;
            if(nx>=1&&nx<=r&&ny>=1&&ny<=c&&a[nx][ny]!='#'){//不越界的同时不是障碍
                if(np==0){//人
                if(a[nx][ny]=='.'&&dis[nx][ny]==-1){//空地+没走过 不能走火
                dis[nx][ny]=dis[tx][ty]+1;//更新距离
                q.push({nx,ny,0});
                }
                }
                else if(np==1){//火
                if(a[nx][ny]!='F'){//注意下一个不能是火 不然会导致重复状态
                a[nx][ny]='F';
                q.push({nx,ny,1});
                }
                }
                }
            }
        }
        cout<<"IMPOSSIBLE";
    }
    signed main(){
        ios::sync_with_stdio(0);
        cin.tie(0);
        cin>>r>>c;
        for(int i=1;i<=r;i++){
            for(int j=1;j<=c;j++){
                cin>>a[i][j];
                dis[i][j]=-1;//初始化
                if(a[i][j]=='J'){
                    sx=i,sy=j;
                }
                if(a[i][j]=='F'){
                  f.push_back({i,j,1});//把火全部放进数组中 在bfs开始时先入队
                }
            }
        }
        if(sx==1||sx==r||sy==1||sy==c){//特判一下开局就可以跑出去
            cout<<1;
            return 0;
        }
        bfs(sx,sy,0);
    }
    
    • 0
      @ 2026-4-7 20:56:16

      是个好模板题 不难但是ex

      #include<bits/stdc++.h>
      using namespace std;
      #define int long long
      /* n*m J是人的位置:.是路 #是墙 F是火(可能有多个) 火不断向四周蔓延 J逃跑到墙外就可以算成功了 
        问:j逃出去花费的最少时间 如果出不去返回IMPOSSIBLE 、
        //okok 来看看本题:本题其实是一个模板:多源BFS记时
        1:我们可以利用F 求出F【】【】 即火到各个地方的最短时间
        2:对于人我们要求 a[][]即走到每部的时间 
      */
      #define PII pair<int,int> 
      const int N=1200;
      char g[N][N];
      int a[N][N];
      int f[N][N];
      int n,m;
      int ans=1e9;
      int dx[]={1,-1,0,0};
      int dy[]={0,0,-1,1};
      bool check(int x,int y)
      {
      	if(x<0||x>n-1||y<0||y>m-1) return 0;
      	return 1;
      }
      void bfs()
      {
        queue<PII> q;
        for(int i=0;i<n;i++)//先初始化 放入所有单原 
         for(int j=0;j<m;j++)
         {
         	 if(g[i][j]=='F')
         	 {
         	 	q.push({i,j});
      		f[i][j]=0;	 
      	 }
         }
        while(q.size())
        {
          auto t=q.front();
          q.pop();
      	int xx=t.first;
      	int yy=t.second;
      	for(int i=0;i<4;i++)
      	{
      	  int nx=xx+dx[i];
      	  int ny=yy+dy[i];
      	  if(check(nx,ny)&&f[nx][ny]==0)
      	   {
      	     f[nx][ny]=f[xx][yy]+1;
      		 q.push({nx,ny});	
      	   }	
      	}	
        }
        return;	
      }
      void bfs2(int x,int y,int s[][N])//这俩代码相似复制修 
      { 
        queue<PII> q;
        q.push({x,y});
        a[x][y]=0; 
        while(q.size())
        { 
          auto t=q.front();
          q.pop();
      	int xx=t.first;
      	int yy=t.second;
      	//先判定终点
      	if(!check(xx,yy)) 
      	{ ans=s[xx][yy];
      	  break;//第一个出去的就行 
          }
      	for(int i=0;i<4;i++)
      	{
      	  int nx=xx+dx[i];
      	  int ny=yy+dy[i];
      	 if(s[nx][ny]==0 && (f[nx][ny]==0 || s[xx][yy]+1 < f[nx][ny]))
      	 //1:要看能不能走出去不要check 2走到下一步火还没来3不重复不撞墙 
      	   {
      	     s[nx][ny]=s[xx][yy]+1;
      		 q.push({nx,ny});	
      	   }	
      	}	
        }
        return;		
      }
      signed main()
      { std::ios::sync_with_stdio(0);
        cin.tie(0),cout.tie(0);
        cin>>n>>m;
        int x1,y1;//j的位置 
        for(int i=0;i<n;i++)
         for(int j=0;j<m;j++)
         {
           cin>>g[i][j];
      	 if(g[i][j]=='#') a[i][j]=-1,f[i][j]=-1; 
      	 if(g[i][j]=='J') x1=i,y1=j;	
         }	
       //1得到火焰数组 注意只要是火焰就先加入q
        bfs(); 
       //ok再来看J	 
        bfs2(x1,y1,a);
        if(ans==1e9) cout<<"IMPOSSIBLE"<<"\n";
        else cout<<ans<<"\n";  
      	return 0;
      }
      
      • 1

      信息

      ID
      524
      时间
      1000ms
      内存
      256MiB
      难度
      3
      标签
      递交数
      163
      已通过
      35
      上传者