2 条题解
-
1
由于火可以蔓延到四周,人也可以前往四周(除了#的地方)所以我们可以在结构体中多加入状态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
是个好模板题 不难但是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
- 上传者