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

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



詭異的樓梯

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 13186    Accepted Submission(s): 3318


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
Hint 地圖如下:

本題與簡單B模板BFS題的區別就在於對樓梯的處理。這值得注意的一點就是要考慮等樓梯的情況。

因為這種情況的存在,因此採用優先佇列保證得到的時間是最小的。

具體對樓梯的處理體現在程式碼中。

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<stack>


using namespace std;


char map[1001][1001];
int vis[1001][1001];


int n,m,sx,sy,ex,ey;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1},};


bool legal(int x,int y)
{
    if(x<1||y<1||x>n||y>m||vis[x][y]||map[x][y]=='*')
        return false;
    return true;
}


struct node
{
    int x,y,t;
};


struct cmp
{
    bool operator()(node a,node b)
    {
        return a.t>b.t;
    }
};


int bfs()
{
    memset(vis,0,sizeof(vis));
    node cur,next;
    cur.x=sx;
    cur.y=sy;
    cur.t=0;
    priority_queue<node,vector<node>,cmp> q;
    q.push(cur);
    while(!q.empty())
    {
        cur=q.top();
        q.pop();
        if(cur.x==ex&&cur.y==ey) return cur.t;
        for(int i=0;i<4;i++)
        {
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];
            next.t=cur.t+1;
            while(legal(next.x,next.y))
            {
                if((i==0||i==1)&&map[next.x][next.y]=='|'&&cur.t%2==0)
                        next.x=next.x+dir[i][0];
              else  if((i==0||i==1)&&map[next.x][next.y]=='-'&&cur.t%2==0)
                {
                    next.x=next.x+dir[i][0];
                    next.t=next.t+1;
                }


              else  if((i==0||i==1)&&map[next.x][next.y]=='-'&&cur.t%2==1)
                        next.x=next.x+dir[i][0];
                else  if((i==0||i==1)&&map[next.x][next.y]=='|'&&cur.t%2==1)
                {
                      next.x=next.x+dir[i][0];
                        next.t=next.t+1;
                }


              else  if((i==2||i==3)&&map[next.x][next.y]=='|'&&cur.t%2==1)
                        next.y=next.y+dir[i][1];
                else  if((i==2||i==3)&&map[next.x][next.y]=='|'&&cur.t%2==0)
                {
                    next.y=next.y+dir[i][1];
                    next.t=next.t+1;
                }
              else  if((i==2||i==3)&&map[next.x][next.y]=='-'&&cur.t%2==0)
                        next.y=next.y+dir[i][1];
            else  if((i==2||i==3)&&map[next.x][next.y]=='-'&&cur.t%2==1)
            {
                next.y=next.y+dir[i][1];
                    next.t=next.t+1;
            }
            vis[next.x][next.y]=1;
              q.push(next);
            }
        }


    }
}


int main()
{
    while(cin>>n>>m)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
        {
            cin>>map[i][j];
            if(map[i][j]=='S')
            {
                sx=i;
                sy=j;
                map[i][j]='*';
            }
            if(map[i][j]=='T')
            {
                ex=i;
                ey=j;
            }
        }
        cout<<bfs()<<endl;
    }
    return 0;
}