【棋盘上的BFS】滑旱冰

【问题描述】
经过跟FJ长达数年的谈判,奶牛们终于如愿以偿地得到了想要的旱冰鞋。农场上大部分的区域都是平整的,适合在上面滑动,但有一些小块的土地上有很多岩石,凭奶牛们的旱冰技术,是没有办法通过的。农场可以看成被划分成R行C列的矩阵。快要开饭了,贝西发现自己在坐标为(1,1)的格子里,并且它想赶到坐标为(R,C)的格子的牛棚去享受晚饭。贝西以她所在格子为起点,每 1 秒可以向它面朝的方向(东、南、西、北)滑动到下一个格子,或者在原地向左转或右转一次。当然任何时候,她都不能滑出农场和滑到有岩石的格子。现在请你帮贝西计算,他最早经过多少秒才能到达(R,C)。注意,贝西在起点左转或右转不花时间,同理,在终点面的朝向无所谓,只要到达(R,C)即可。

【输入格式】
第 1 行:两个空格分开的整数R和C。。
第 2 到第 R+1 行:每行包含 C 个字符,字符可能是 ‘.’ 或 ‘’ ,’.’ 表示贝西能从格子里通过,’’ 表示不能通过的岩石地带

【输出格式】
一个整数,最短时间

【输入样例】

5 8
..*...**
*.*.*.**
*...*...
*.*.*.*.
....*.*. 

【输出样例】

22

【数据范围】
1<=R,C<=113

【来源】
Mr_He原创

/*
    Name: Roller_Skating
    Copyright: Twitter & Instagram @stevebieberjr
    Author: @stevebieberjr
    Date: 08/07/16 21:41
*/
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;

int dx[4]={0,1,0,-1}; //往 东 南 西 北 的坐标变化 
int dy[4]={1,0,-1,0};
int dist[120][120][4]={0}; //dist[X][Y][DIR] 从(1,1)到(x,y)面朝dir方向时的最短距离 
int inq[120][120][4];
int R,C;
char a[120][120]={0};

struct xy
{
    int x,y,dir; //dir: 0面朝东 1面朝南 2面朝西 3面朝北 
};

void init()
{
    scanf("%d%d",&R,&C);
    for(int i=1;i<=R;i++)
    {
        char t;
        scanf("%c",&t);
        for(int j=1;j<=C;j++)
        {
            char t;
            scanf("%c",&t);
            if(t=='*') 
            a[i][j]=1; //将有障碍的坐标赋值为1 
        }
    }
}

void BFS()
{
    queue<xy>q;

    q.push((xy){1,1,0}); //在起点时面向东
    dist[1][1][0]=0;
    inq[1][1][0]=1;

    q.push((xy){1,1,1}); //在起点时面向南
    dist[1][1][1]=0;
    inq[1][1][1]=1;

    xy t,tt;

    while(!q.empty())
    {
        t=q.front();
        q.pop();

        //不改变方向
        tt.x=t.x+dx[t.dir];
        tt.y=t.y+dy[t.dir];
        tt.dir=t.dir;
        if(a[tt.x][tt.y]==0)
        if(tt.x<=R && tt.x>=1 && tt.y<=C && tt.y>=1)
        if(inq[tt.x][tt.y][tt.dir]==0)
        {
            q.push(tt);
            dist[tt.x][tt.y][tt.dir]=dist[t.x][t.y][t.dir]+1;
            inq[tt.x][tt.y][tt.dir]=1;
        }

        //向右转
        tt.x=t.x;
        tt.y=t.y;
        tt.dir=(t.dir+1)%4;
        if(inq[tt.x][tt.y][tt.dir]==0)
        {
            q.push(tt);
            dist[tt.x][tt.y][tt.dir]=dist[t.x][t.y][t.dir]+1;
            inq[tt.x][tt.y][tt.dir]=1;
        }

        //向左转
        tt.x=t.x;
        tt.y=t.y;
        tt.dir=(t.dir+3)%4;
        if(inq[tt.x][tt.y][tt.dir]==0)
        {
            q.push(tt);
            dist[tt.x][tt.y][tt.dir]=dist[t.x][t.y][t.dir]+1;
            inq[tt.x][tt.y][tt.dir]=1;
        }
    }
}

int main()
{
    init();
    BFS();
    int ans=min(dist[R][C][0],min(dist[R][C][1],min(dist[R][C][2],dist[R][C][3]))); //在四个方向的结果中找最小值 
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值