杭电1180——诡异的楼梯(BFS+优先队列)

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1180

主要算法:遇到楼梯时,如果楼梯方向和前进方向一致且通过楼梯的下一格能走,则前进且时间加一。如果楼梯方向和前进方向不一致,则在原地等一分钟。 至于楼梯方向的判断,无需每时每刻都改变一下楼梯的方向,只需根据当前时间,如果时间为偶数,则楼梯方向与初始方向一样,如果时间为奇数,则楼梯方向和初始方向相反。ps:做了快两天一直WA,怎么都看不出算法哪里有问题,后来发现题目中写的输入是多组数据,我只处理一组数据,看清题目啊.....

# include<iostream>
# include<queue>
using namespace std;

char maze[22][22];
int visited[22][22];
int waited[22][22];
int m,n,startx,starty,endx,endy;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

typedef struct Point{
    int x,y,time;//横坐标x,纵坐标y,时间time
    bool operator <(const Point &p) const{
        return time>p.time;//最小值优先
    }
}Point;

priority_queue<Point> q;

int bfs();

int main()
{
    while(cin>>m>>n)
    {
        if(m==0&&n==0)
            continue;
        int i,j;
        memset(visited,0,sizeof(int)*22*22);
        memset(waited,0,sizeof(int)*22*22);
        for(i=0;i<m;i++)
        {
            for(j=0;j<n;j++)
            {
                cin>>maze[i][j];
                if(maze[i][j]=='S')
                {
                    startx=i;
                    starty=j;
                }
                else if(maze[i][j]=='T')
                {
                    endx=i;
                    endy=j;
                }
            }
        }
        printf("%d\n",bfs());
    }

    return 0;
}

int bfs()
{
    Point t,nt;
    t.x=startx;
    t.y=starty;
    t.time=0;
    q.push(t);
    visited[startx][starty]=1;
    while(!q.empty())
    {
        t=q.top();
        q.pop();
        if(t.x==endx&&t.y==endy)
            return t.time;
        int nx,ny,k;
        for(k=0;k<4;k++)
        {
            nx=t.x+dir[k][0];
            ny=t.y+dir[k][1];
            if(nx>=0&&nx<m&&ny>=0&&ny<n&&maze[nx][ny]!='*'&&!visited[nx][ny])
            {
                if(maze[nx][ny]=='.'||maze[nx][ny]=='T')
                {
                    nt.x=nx;
                    nt.y=ny;
                    nt.time=t.time+1;
                    visited[nx][ny]=1;
                    q.push(nt);
                }
                //待扩展的节点为楼梯
                else if(maze[nx][ny]=='|'||maze[nx][ny]=='-')
                {
                    //往左右方向扩展
                    if(k/2)
                    {
                            //此时楼梯方向为'-',与扩展方向一致,时间加一既可
                            if((maze[nx][ny]=='-'&&!(t.time%2))||(maze[nx][ny]=='|'&&t.time%2))
                            {
                                if(ny>=-dir[k][1]&&ny<n-dir[k][1]&&maze[nx][ny+dir[k][1]]!='*'&&!visited[nx][ny+dir[k][1]])
                                {
                                    nt.x=nx;
                                    nt.y=ny+dir[k][1];
                                    visited[nt.x][nt.y]=1;
                                    nt.time=t.time+1;
                                    q.push(nt);
                                }
                            }
                            else if(!waited[t.x][t.y])
                            {
                                nt.x=t.x;
                                nt.y=t.y;
                                visited[nt.x][nt.y]=1;
                                waited[nt.x][nt.y]=1;
                                nt.time=t.time+1;//在原地等一分钟
                                q.push(nt);
                            }

                    }
                    //上下方向扩展
                    else
                    {
                            //楼梯方向为'|',扩展方向与楼梯方向一致
                            if((maze[nx][ny]=='|'&&!(t.time%2))||(maze[nx][ny]=='-'&&t.time%2))
                            {
                                if(nx>=-dir[k][0]&&nx<m-dir[k][0]&&maze[nx+dir[k][0]][ny]!='*'&&!visited[nx+dir[k][0]][ny])
                                {
                                    nt.x=nx+dir[k][0];
                                    nt.y=ny;
                                    visited[nt.x][nt.y]=1;
                                    nt.time=t.time+1;
                                    q.push(nt);
                                }
                            }
                            else if(!waited[t.x][t.y])
                            {
                                nt.x=t.x;
                                nt.y=t.y;
                                visited[nt.x][nt.y]=1;
                                waited[nt.x][nt.y]=1;
                                nt.time=t.time+1;
                                q.push(nt);
                            }

                    }
                }
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值