独轮车(BFS)

【问题描述】

  独轮车是一种仅有一个轮子的特殊自行车。他的轮子被等分成5个扇形,分别涂上一种不同的颜色。现在有一个人骑自行车行驶在M*N的网格平面上。每个格子的大小恰好使得当车从一个格子骑到下一个格子时,轮子恰好转过一个扇形。

  如下图所示,当轮子在1号格子的中心时,蓝色扇形的外弧线中线刚好于地面接触。当它移动到下一个格子(2号格子)的时候,白色扇形的外弧线于地面接触。 这里写图片描述
     
  有些各自中有障碍,所以车子不能通过这些格子。骑车人从某个格子出发,希望用最短的时间移动到目标格。在任何一个格子上,他要么骑到下一个格子,要么左转或者右转90度。其中每项动作恰好需要1秒来完成。初始时,他面朝北且绿色扇形贴着地面。到达目标格时,也必须是绿色扇形贴着地面,但朝向无限制。如下图所示。
      
  这里写图片描述

【输入格式】

  第一行包含两个整数M和N(1<=m,n<=100),表示迷宫的行数和列数,接下来是网格的描述,用M行长度为N的字符串来表示。字符#表示一个障碍方格,其他方格均可通行。骑车人的起点用S表示,终点用T表示。

【输出格式】

  输出测试数据编号和到达目标格的最短时间(单位:秒)。如果无法到达,输出“destination not reachable”。

【输入样例】

【样例1】
1 3
S#T

【样例2】
10 10

#S.......#
#..#.##.##
#.##.##.##
.#....##.#
##.##..#.#
#..#.##...
#......##.
..##.##...
#.###...#.
#.....###T

【输出样例】

【样例1】
destination not reachable

【样例2】
minimum time = 49 sec

【数据范围】

1<=m,n<=100

这道题就是棋盘BFS遍历,只不过状态多了一些,注意处理好每一个动作相应的状态的改变就可以了。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=105;
int n,m,sx,sy,ex,ey,d[maxn][maxn][10][10],vis[maxn][maxn][10][10];
int dx[]={0,1,0,-1};//dir:E,S,W,N
int dy[]={-1,0,1,0};
char mat[maxn][maxn];
//color:green,white,blue,red,black
struct data
{
    int x,y,dir,c;
};

void bfs()
{
    queue<data>q;
    q.push((data){sx,sy,3,0});
    memset(vis,0,sizeof(vis));
    d[sx][sy][3][0]=0;
    vis[sx][sy][3][0]=1;
    int ok=0;
    data ans;

    while(!q.empty())
    {
        data t=q.front(); q.pop();
        if(t.x==ex&&t.y==ey&&t.c==0)
        {
            ok=1;
            ans=t;
            break;
        }

        data tt;

        tt.x=t.x+dx[t.dir];
        tt.y=t.y+dy[t.dir];
        tt.dir=t.dir;
        tt.c=(t.c+1)%5;
        if(tt.x>=1&&tt.y>=1&&tt.x<=m&&tt.y<=n)
        if(mat[tt.x][tt.y]!='#')
        if(vis[tt.x][tt.y][tt.dir][tt.c]==0)
        {
            d[tt.x][tt.y][tt.dir][tt.c]=d[t.x][t.y][t.dir][t.c]+1;
            vis[tt.x][tt.y][tt.dir][tt.c]=1;
            q.push(tt);
        }

        tt.x=t.x;
        tt.y=t.y;
        tt.dir=(t.dir+1)%4;
        tt.c=t.c;
        if(tt.x>=1&&tt.y>=1&&tt.x<=m&&tt.y<=n)
        if(mat[tt.x][tt.y]!='#')
        if(vis[tt.x][tt.y][tt.dir][tt.c]==0)
        {
            d[tt.x][tt.y][tt.dir][tt.c]=d[t.x][t.y][t.dir][t.c]+1;
            vis[tt.x][tt.y][tt.dir][tt.c]=1;
            q.push(tt);
        }

        tt.x=t.x;
        tt.y=t.y;
        tt.dir=(t.dir-1+4)%4;
        tt.c=t.c;
        if(tt.x>=1&&tt.y>=1&&tt.x<=m&&tt.y<=n)
        if(mat[tt.x][tt.y]!='#')
        if(vis[tt.x][tt.y][tt.dir][tt.c]==0)
        {
            d[tt.x][tt.y][tt.dir][tt.c]=d[t.x][t.y][t.dir][t.c]+1;
            vis[tt.x][tt.y][tt.dir][tt.c]=1;
            q.push(tt);
        }
    }
    if(ok) printf("minimum time = %d sec",d[ans.x][ans.y][ans.dir][ans.c]);
    else printf("destination not reachable");
}

int main()
{
    //freopen("1.txt","r",stdin);
    //freopen("matrix.out","w",stdout);

    scanf("%d%d",&m,&n);

    for(int i=1;i<=m;i++)
    {
        scanf("%s",mat[i]+1);
        for(int j=1;j<=n;j++)
        {
            if(mat[i][j]=='S') sx=i,sy=j;
            if(mat[i][j]=='T') ex=i,ey=j;
        }
    }
    bfs();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值