UVa - 10047 The Monocycle 独轮车 多状态BFS 重庆一中高2018级竞赛班第十一次测试 2016.9.24 Problem 4

注:原题为多组数据。本题输入改为只有一组数据。
【问题描述】
独轮车是一种仅有一个轮子的特殊自行车。他的轮子被等分成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

思路:使用d[x][y][dir][cor]来记录从起点到(x,y)格子,面朝dir方向,轮子颜色为cor时的最短时间。

#include<cstdio>
using namespace std;

const int maxn=105;
const int inf=200000000;
struct shu
{
    int x,y,fang,color;
}b,v;

int n,m,ok=0;
char a[maxn][maxn];
int d[maxn][maxn][5][5];
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
bool vis[maxn][maxn][5][5]={0};
shu q[maxn*maxn*10*10];

void init()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",a[i]+1);
        for(int j=1;j<=m;j++)
        {
            if(a[i][j]=='S')  b.x=i,b.y=j;
            if(a[i][j]=='T')  v.x=i,v.y=j;
        }
    }
}

void bfs(shu t)
{
    int root=0,frond=0;
    q[root++]=(shu){t.x,t.y,3,0};
    vis[t.x][t.y][3][0]=1;
    d[t.x][t.y][3][0]=0;
    shu i,tt;
    while(root!=frond)
    {
        i=q[frond++];
        //1前 
        tt.x=i.x+dx[i.fang];
        tt.y=i.y+dy[i.fang];
        tt.fang=i.fang;
        tt.color=(i.color+1)%5;
        if(a[tt.x][tt.y]!='#')
        if(tt.x<=n&&tt.x>=1&&tt.y<=m&&tt.y>=1)
        if(vis[tt.x][tt.y][tt.fang][tt.color]==0)
        {
            q[root++]=tt;
            d[tt.x][tt.y][tt.fang][tt.color]=d[i.x][i.y][i.fang][i.color]+1;
            vis[tt.x][tt.y][tt.fang][tt.color]=1;
            if(tt.x==v.x&&tt.y==v.y&&tt.color==0)
            {
                printf("minimum time = %d sec\n",d[tt.x][tt.y][tt.fang][tt.color]);
                ok=1;
                return;
            }
        }
        //2右
        tt=i;
        tt.fang=(i.fang+1)%4;
        if(vis[tt.x][tt.y][tt.fang][tt.color]==0)
        {
            q[root++]=tt;
            d[tt.x][tt.y][tt.fang][tt.color]=d[i.x][i.y][i.fang][i.color]+1;
            vis[tt.x][tt.y][tt.fang][tt.color]=1;
        }
        //3左
        tt=i;
        tt.fang=(i.fang+3)%4;
        if(vis[tt.x][tt.y][tt.fang][tt.color]==0)
        {
            q[root++]=tt;
            d[tt.x][tt.y][tt.fang][tt.color]=d[i.x][i.y][i.fang][i.color]+1;
            vis[tt.x][tt.y][tt.fang][tt.color]=1;
        }
    }
}
int main()
{
    //freopen("monocycle.in","r",stdin);
    //freopen("monocycle.out","w",stdout);
    init();
    bfs(b);
    if(!ok) printf("destination not reachable\n");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值