HDU:诡异的楼梯

来源:互联网 发布:用户数据分析报告 编辑:程序博客网 时间:2024/06/09 15:24

诡异的楼梯

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


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


题目代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stdlib.h>
#define INF 0x3f3f3f3f
#define min(a,b) a<b? a:b
using namespace std;
char Map[200][200];
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};//四个方向
int vis[200][200]; //用于标记的数组
int M,N;//M行N列
struct pos
{
    int x,y,step;//横坐标,纵坐标,步数
};
pos start,eend;//起点、终点
int judge(int x1,int y1,int step,int i)//坐标(楼梯坐标),步数(当前步数),方向
{
    int x=x1+dir[i][0]; //先判断楼梯对面有没有到过
    int y=y1+dir[i][1];
    if(vis[x][y]) //如果楼梯对面已经被访问过了,那么说明之前到过的点更早
        return -1;
    int time1=0;  
    if(step%2==0) //到楼梯处的前一步是偶数,那么当前我楼梯的状态是与原来相同的
    {
        if(Map[x1][y1]=='|') //原来是竖着的,现在还是竖着的。
        {
            if(dir[i][0]==0) //横坐标变化为0,现在在水平方向上
                time1++;  //只需等一秒就可以直接过去
        }
        else  //楼梯是横着的
        {
            if(dir[i][1]==0) //纵坐标变化为0,现在在竖直方向上
                time1++;  //只需等一秒就可以直接过去
        }
    }
    else//步数为奇数,此时楼梯的状态与初始时刻是相反的
    {
        if(Map[x1][y1]=='|') //此时楼梯为横的
        {
            if(dir[i][1]==0) //如果在竖直方向,就要等一分就可以直接过去
                time1++;
        }
        if(Map[x1][y1]=='-')   //楼梯在这一秒为竖的
        {
            if(dir[i][0]==0) //如果现在在水平方向上,我就要等一分钟就可以直接过去
                time1++;
        }
    }
    return time1+1;//最后加1是走到楼梯位置是需要1分钟的
}
int bfs()
{
    int i;
    pos cur,nex;
    memset(vis,0,sizeof(vis));
    vis[start.x][start.y]=1; //先将起点位置标记
    queue<pos>Q;
    Q.push(start);
    while(!Q.empty())
    {
        cur=Q.front();
        Q.pop();
        if(cur.x==eend.x&&cur.y==eend.y)//如果当前位置为终点的位置
            return cur.step;
        for(i=0;i<4;i++)
        {
            nex.x=cur.x+dir[i][0];
            nex.y=cur.y+dir[i][1];
            if(nex.x>0&&nex.x<=M&&nex.y>0&&nex.y<=N&&vis[nex.x][nex.y]==0)//合法且没有到过
            {
                if(Map[nex.x][nex.y]=='.'||Map[nex.x][nex.y]=='T')//能够行走
                {
                    vis[nex.x][nex.y]=1;
                    nex.step=cur.step+1;
                    Q.push(nex);
                }
                else if(Map[nex.x][nex.y]=='|'||Map[nex.x][nex.y]=='-')//如果是楼梯
                {

                    int temp=judge(nex.x,nex.y,cur.step,i);//判断
                    if(temp==-1)//不过楼梯
                        continue;
                    nex.x=nex.x+dir[i][0]; //走到楼梯对面
                    nex.y=nex.y+dir[i][1];
                    vis[nex.x][nex.y]=1;  //标记这个位置
                    nex.step=cur.step+temp; //加上步数
                    Q.push(nex);    //入队
                }
            }
        }
    }
    return -1;
}
int main()
{
    int k,j,ans;
    while(~scanf("%d%d",&M,&N))  //M行,N列
    {
        for(j=1;j<=M;j++)
            for(k=1;k<=N;k++)
            {
                scanf(" %c",&Map[j][k]);
                if(Map[j][k]=='S')
                {
                    start.x=j;
                    start.y=k;
                    start.step=0;
                }
                if(Map[j][k]=='T')
                {
                    eend.x=j;
                    eend.y=k;
                }
            }
        ans=bfs();
        printf("%d\n",ans);
    }
    return 0;
}

0 0
原创粉丝点击