懒病发作了小半年···咳···终于想起我原来还有个博客啊···
这月刷大白的图论···第一道题就坑了一下午···因为我判出边界之后只break出一层循环···【哭晕在厕所
题意:小J童鞋要逃离一个着火的迷宫,火蔓延的速度跟小J童鞋跑的速度一样,都是一分钟一格,方向都是上下左右四个方向,求小J逃离迷宫的最短时间,如果跑不掉输出“IMPOSSIBLE"。
解法:两次BFS。因为火只会蔓延不会熄灭,所以先做一次BFS记录每个点最早着火时间,在BFS小J逃跑路线的时候加到判断里,搜索到边界时得到答案。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<map> #include<queue> #define ll long long using namespace std; struct node { int i,j,step; node(int i,int j,int step):i(i),j(j),step(step){}//在某人那里学来的初始化结构体的方法TUT node(){} }; queue<node> q; int n,m; char MAP[1005][1005];//迷宫地图 int fire[1005][1005];//每个点的最早起火时间 int visit[1005][1005]; int dir[4][2]= {-1,0,0,-1,0,1,1,0}; int main() { int T; scanf("%d",&T); while(T--) { while(!q.empty()) q.pop(); for(int i=0; i<1005; i++) for(int j=0; j<1005; j++) fire[i][j]=10000000; memset(visit,0,sizeof(visit)); int bi,bj; scanf("%d%d",&n,&m); for(int i=0; i<n; i++) scanf("%s",MAP[i]); for(int i=0; i<n; i++) for(int j=0; j<m; j++) { if(MAP[i][j]=='F') { fire[i][j]=0; q.push(node(i,j,0));//把初始的起火点压入队列 visit[i][j]=1; } if(MAP[i][j]=='J') { bi=i; bj=j;//记录小J童鞋的起点 } if(MAP[i][j]=='#') fire[i][j]=-1;//将墙初始化为-1,在BFS小J的逃跑路线时不用再判断墙壁了 } while(!q.empty()) { node p=q.front(); q.pop(); for(int i=0; i<4; i++) { int ti=p.i+dir[i][0],tj=p.j+dir[i][1]; if(ti>=0&&ti<n&&tj>=0&&tj<m&&fire[p.i][p.j]+1<fire[ti][tj]) { fire[ti][tj]=p.step+1; if(!visit[ti][tj]) { visit[ti][tj]=1; q.push(node(ti,tj,p.step+1)); } } } }//得到起火时间的表 int ans=-1; memset(visit,0,sizeof(visit)); visit[bi][bj]=1; q.push(node(bi,bj,0)); while(!q.empty()) { node p=q.front();//【吐槽】p和q,傻傻分不清楚··· q.pop(); for(int i=0; i<4; i++) { int ti=p.i+dir[i][0],tj=p.j+dir[i][1]; if(ti>=0&&ti<n&&tj>=0&&tj<m) { if(!visit[ti][tj]&&(p.step+1<fire[ti][tj]))//判断走到这的时间是否早于起火时间 { visit[ti][tj]=1; q.push(node(ti,tj,p.step+1)); } } else { ans=p.step+1; } if(ans!=-1) break; } if(ans!=-1) break;//【吐槽】因为没写这句话wa了一下午···orz还是太菜了 } if(ans!=-1) printf("%d ",ans); else puts("IMPOSSIBLE"); } return 0; }
代码丑···见谅