XTU-OJ 1356-Maze

题目描述

一个n∗m格子的迷宫,'.'表示道路,'*'表示墙,'S'表示起点,'E'表示终点。一个机器人一开始在起点,如果在它的方向前是道路,每次能往前走一格;如果在它的方向前是墙或者迷宫边界,它会右转90∘。请问机器人从起点到终点最少走多少步?

输入

第一行是一个整数T(1≤T≤100),表示样例的个数。 每个样例第一行是三个整数,为n,m(1≤n,m≤100),d(1≤d≤4),n,m表示迷宫的行、列大小, d表示机器人一开始的方向,1∼4依次表示"上右下左"。 以后的n行是迷宫的情况,数据保证S和E不重合。

输出

每行输出一个样例的结果,如果无法走出迷宫,输出"Impossible"

样例输入

2
3 4 2
S...
***.
E...
3 4 2
S...
....
E.*.

样例输出

8
Impossible

解题思路:这题就是模拟题咯,老生常谈了,模拟题不难,就是很麻烦。它不会像其他思维题或数学题那样让你完全找不到头绪,只需要让你费费脑子,把头绕晕,再掉掉头发就好。 

代码思路就是按照题目所说的去模拟,而无解判断是 行走步数>n*m (就相当于把所有地方都走了一遍还是没找到出口,但有人会问,为什么呢?万一它只是在一段路上来回走了一趟,消耗了一些步数,后面还是有机会找到出口的。非也,你要想机器人是只会直行和右转的,如果它在一段路上走了个来回,那么它一定是迷路了,会一直陷入这段路中出不来的) 和 flag>4(连续转向四次,四周都是墙)

AC代码:

#include <stdio.h>

char maps[105][105];
int T,n,m,d,x,y,ans,flag;
int tags[6][3] = {{0,0},{-1,0},{0,1},{1,0},{0,-1}};

int main()
{
    scanf("%d",&T);
    while ( T --)
    {
        int flagS = 1;
        scanf("%d %d %d",&n,&m,&d);
        for (int i = 1; i <= n; i ++)
        {
            scanf("%s",maps[i]+1);
            if (flagS)
            {
                for(int j = 1; j <= m; j ++)
                {
                    if (maps[i][j] == 'S')  
                        x = i, y = j, flagS = 0;   // x,y是矩阵里的行列数, x是行、y是列,放在直角坐标系里(x为纵坐标、y为横坐标)
                }
            }
        }
        flag = ans = 0;
        while (maps[x][y] != 'E')
        {
            if ((d==1 && x==1) || (d==2 && y==m) || (d==3 && x==n) || (d==4 && y==1) || maps[x+tags[d][0]][y+tags[d][1]] == '*')
            {
                d = d%4+1;                          // 右转向
                flag ++;
            }
            else
            {
                x += tags[d][0], y += tags[d][1];   // 移动
                flag = 0, ans ++;
            }
            if (ans > n*m || flag > 4)  {ans = 0;break;}    // 无答案条件
        }
        if (ans)    printf("%d\n",ans);
        else        puts("Impossible");
    }
    return 0;
}

还有个 用三位数组标记的方法也贴上(这个更好理解,一旦在某个位置,重复方向前进后,那么说明又要走之前相同的路了,那也就是迷路)

#include <stdio.h>

int T,n,m,d,x,y,ans;
int tags[6][3] = {{0,0},{-1,0},{0,1},{1,0},{0,-1}};
char maps[102][102];

int main()
{
    scanf("%d",&T);
    while ( T --)
    {
        int flagS = 1;
        int books[102][102][5] = {0};
        scanf("%d %d %d",&n,&m,&d);
        for (int i = 1; i <= n; i ++)
        {
            scanf("%s",maps[i]+1);
            if (flagS)
            {
                for(int j = 1; j <= m; j ++)
                {
                    if (maps[i][j] == 'S')  
                        x = i, y = j, flagS = 0;   // x,y是矩阵里的行列数, x是行、y是列,放在直角坐标系里(x为纵坐标、y为横坐标)
                }
            }
        }
        ans = 0;
        while (maps[x][y] != 'E')
        {
            if ((d==1 && x==1) || (d==2 && y==m) || (d==3 && x==n) || (d==4 && y==1) || maps[x+tags[d][0]][y+tags[d][1]] == '*')
            {
                d = d%4+1;                          // 右转向
                books[x][y][d] ++;
            }
            else
            {
                x += tags[d][0], y += tags[d][1];   // 移动
                books[x][y][d] ++;
                ans ++;
            }
            if (books[x][y][d] == 2)   {ans = 0;break;}
        }
        if (ans)    printf("%d\n",ans);
        else        puts("Impossible");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值