1. 程式人生 > >hdu1180 詭異的樓梯(BFS+優先佇列)

hdu1180 詭異的樓梯(BFS+優先佇列)

詭異的樓梯

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&lt;=20,地圖中不會出現兩個相連的梯子.Harry每秒只能停留在'.'或'S'和'T'所標記的格子內.

Output 只有一行,包含一個數T,表示到達目標的最短時間.
注意:Harry只能每次走到相鄰的格子而不能斜走,每移動一次恰好為一分鐘,並且Harry登上樓梯並經過樓梯到達對面的整個過程只需要一分鐘,Harry從來不在樓梯上停留.並且每次樓梯都恰好在Harry移動完畢以後才改變方向.

Sample Input 5 5 **..T **.*. ..|.. .*.*. S....
Sample Output 7 Hint
Hint 地圖如下:

開始wa了很多次,原來是題意沒搞清,還以為只有例子中' |' 這一種樓梯的符號,原來還有’-‘!

要點: 優先佇列的構造,判斷條件的抽取,特殊條件(等待一秒在前進)

優先佇列,使得當前時間小的先出佇列,

所以當前座標的結構體需要這樣寫

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;
因為使用了優先佇列,所以不再用傳統的vis標記是否走過,對於一個已經走過的位置,如果當前step小於之前的step,則可以重複走,

所以用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;
}