hdu1180 詭異的樓梯(BFS+優先佇列)
阿新 • • 發佈:2019-02-14
詭異的樓梯
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 10827 Accepted Submission(s): 2694
Problem Description Hogwarts正式開學以後,Harry發現在Hogwarts裡,某些樓梯並不是靜止不動的,相反,他們每隔一分鐘就變動一次方向.
比如下面的例子裡,一開始樓梯在豎直方向,一分鐘以後它移動到了水平方向,再過一分鐘它又回到了豎直方向.Harry發現對他來說很難找到能使得他最快到達目的地的路線,這時Ron(Harry最好的朋友)告訴Harry正好有一個魔法道具可以幫助他尋找這樣的路線,而那個魔法道具上的咒語,正是由你纂寫的.
Input 測試資料有多組,每組的表述如下:
第一行有兩個數,M和N,接下來是一個M行N列的地圖,'*'表示障礙物,'.'表示走廊,'|'或者'-'表示一個樓梯,並且標明瞭它在一開始時所處的位置:'|'表示的樓梯在最開始是豎直方向,'-'表示的樓梯在一開始是水平方向.地圖中還有一個'S'是起點,'T'是目標,0<=M,N<=20,地圖中不會出現兩個相連的梯子.Harry每秒只能停留在'.'或'S'和'T'所標記的格子內.
Output 只有一行,包含一個數T,表示到達目標的最短時間.
注意:Harry只能每次走到相鄰的格子而不能斜走,每移動一次恰好為一分鐘,並且Harry登上樓梯並經過樓梯到達對面的整個過程只需要一分鐘,Harry從來不在樓梯上停留.並且每次樓梯都恰好在Harry移動完畢以後才改變方向.
Sample Input 5 5 **..T **.*. ..|.. .*.*. S....
Sample Output 7 Hint
開始wa了很多次,原來是題意沒搞清,還以為只有例子中' |' 這一種樓梯的符號,原來還有’-‘!
要點: 優先佇列的構造,判斷條件的抽取,特殊條件(等待一秒在前進)
優先佇列,使得當前時間小的先出佇列,
所以當前座標的結構體需要這樣寫
因為使用了優先佇列,所以不再用傳統的vis標記是否走過,對於一個已經走過的位置,如果當前step小於之前的step,則可以重複走,struct node{ int x,y,step; //兩種方式過載小於號 /* friend bool operator <(node a,node b){ return a.step>b.step; } */ bool operator <(const node &a)const{ return step>a.step;//步數小的先出佇列 } }init;
所以用statue[][]這個陣列儲存走過位置的當前步數;
判斷條件很多,我們把它抽取到函式judge
如果遇到樓梯方向與前進方向不一致,可以等待一秒,再前進bool judge(node no){ //如果超出邊界,或者該位置是牆,或者當前步數大於之前步數,返回false if(no.x<0||no.x>=n||no.y<0||no.y>=m||map[no.x][no.y]=='*'||(statue[no.x][no.y]&&no.step>=statue[no.x][no.y])) return false; return true; }
將這個情況與 一致時的情況放在一起,只是步數不同
【原始碼】
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int n,m;
const int maxn = 21;
int stx,sty,gx,gy;
char map[maxn][maxn];
bool vis[maxn][maxn];
int statue[maxn][maxn];
int dx[4]={0,0,1,-1};
int dy[4]={-1,1,0,0};
struct node{
int x,y,step;
/* friend bool operator <(node a,node b){
return a.step>b.step;
} */
bool operator <(const node &a)const{
return step>a.step;//步數小的先出佇列
}
}init;
bool judge(node no){
//如果超出邊界,或者該位置是牆,或者當前步數大於之前步數,返回false
if(no.x<0||no.x>=n||no.y<0||no.y>=m||map[no.x][no.y]=='*'||(statue[no.x][no.y]&&no.step>=statue[no.x][no.y]))
return false;
return true;
}
int bfs(){
init.x=stx;init.y=sty;init.step=0;
statue[init.x][init.y]=1;
priority_queue<node>pq;
while(!pq.empty())
pq.pop();
pq.push(init);
while(!pq.empty()){
node past=pq.top();
node now;
pq.pop();
for(int i=0;i<4;i++){
now.x=past.x+dx[i];
now.y=past.y+dy[i];
now.step=past.step+1;
if(!judge(now)) continue;
if(map[now.x][now.y]=='|'){
if(now.x==past.x&&(past.step & 1)==0) //當橫著走,且 | 不變
now.step++;
if(now.y==past.y&&(past.step & 1)==1)//當 豎著走 且 |變
{
now.step++;
}
now.x+=dx[i]; now.y+=dy[i];
}
else if(map[now.x][now.y]=='-'){
if(now.x==past.x&&(past.step & 1)==1) //當橫著走,且 -變
now.step++;
if(now.y==past.y&&(past.step & 1)==0)//當豎著走 且-不變
now.step++;
now.x+=dx[i]; now.y+=dy[i];
}
if(!judge(now)) continue;
if(map[now.x][now.y]=='T')
return now.step;
statue[now.x][now.y]=now.step;
pq.push(now);
}
}
return 0;
}
int main(){
while(cin>>n>>m){
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
cin>>map[i][j];
if(map[i][j]=='S')
stx=i,sty=j;
if(map[i][j]=='T')
gx=i,gy=j;
}
memset(statue,0,sizeof(statue));
int ans=bfs();
cout<<ans<<endl;
}
return 0;
}