火在蔓延,人在走。火會蔓延,不會熄滅,我們可以確定某個點着火的時間(廣搜)。對於J來說,要是他走到某點的時間比火蔓延到該點的時間要短,那麼他走到該點的時候,火還沒蔓延過來,他就可以走到該點,否則,不能進入該點。
數據地圖表示:
-1 該點是牆或已經走過,不能走
-2 該點是通道還沒有走過,火還沒蔓延過來,可以走
0-x 該點在第x秒時,火能蔓延到該點
處理過程:
(1)輸入並初始化,初步處理地圖數據
(2)廣搜標記地圖,確定火蔓延情況
(3)廣搜逃亡路線。
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; int n,m; //地圖大小 int sx,sy; //起始位置 int map[1002][1002]; //地圖存儲。“-1”是不能走,“-2” 是能走,“0-x”是火蔓延過來的時間 int dir[4][2]={1,0,0,1,-1,0,0,-1}; //四個方向 struct node //搜索結構體 { int x; int y; int step; }s,e; queue<node> q; //搜索共用隊列 void initial() //地圖,隊列初始化 { int i,j; char x[1002]; //暫存數組 memset(map,-1,sizeof(map)); //全部初始化爲0 while(!q.empty())q.pop(); //情況隊列 cin>>n>>m; for(i=0;i<n;i++) //輸入地圖,並處理 { cin>>x; for(j=0;j<m;j++) { if(x[j]=='.')map[i][j]=-2; //此處可走 else if(x[j]=='F') //此處有火 { map[i][j]=0; s.x=i; s.y=j; s.step=0; q.push(s); } else if(x[j]=='J')sx=i,sy=j; //起點 } //由於最開始全部賦值爲-1,都默認爲不能走,所以,輸入爲“#”時,不用再處理 } while(!q.empty()) //廣度優先搜索,確定火蔓延到每個點的時間【可能蔓延不到】 { s=q.front(); q.pop(); for(i=0;i<4;i++)//四個方向搜索 { e.x=s.x+dir[i][0]; e.y=s.y+dir[i][1]; e.step=s.step+1; if(e.x<0||e.x>=n||e.y<0||e.y>=m||map[e.x][e.y]!=-2)continue; //該點在地圖外面或該點不可被蔓延,不處理該點 map[e.x][e.y]=e.step; //記錄蔓延過來的時間 q.push(e); } } } int bfsescap() //逃亡廣搜,能逃亡成功就返回時間,否則,返回-1 { s.x=sx; s.y=sy; s.step=1; map[sx][sx]=-1; q.push(s); //起點入隊 while(!q.empty()) { s=q.front(); if(s.x==n-1||s.x==0||s.y==m-1||s.y==0) return s.step; //起點要判斷,放這裏更合適【這點的疏忽,讓我鬱悶了三天】逃亡成功 q.pop(); for(int i=0;i<4;i++) //四個方向搜索 { e.x=s.x+dir[i][0]; e.y=s.y+dir[i][1]; e.step=s.step+1; if(e.x<0||e.x>=n||e.y<0||e.y>=m||(map[e.x][e.y]!=-2&&map[e.x][e.y]<e.step))continue; //不可走,不處理 map[e.x][e.y]=-1; q.push(e); } } return -1; //所有能走的地方都走了,還是沒有逃出去。逃亡失敗 } int main() { int t; cin>>t; //案例測試數據組數 while(t--) { initial(); //輸入,賦值處理等初始化 int ans=bfsescap(); //逃亡廣搜 if(ans==-1)cout<<"IMPOSSIBLE"<<endl; //結果分析,所有能走的節點都走過了,還沒有逃出迷宮 else cout<<ans<<endl; } return 0; }