湘大OJ第1492题 I, Robot

  湘大1492题,I, Robot题目链接)。

I, Robot

Description

A robot must obey any orders given to it by human beings,
except where such orders would conflict with the First Law.
- Isaac Asimov

There is a robot trapped in the maze. Now you have to send out some instructions, telling it how to reach its destination.

The maze is an N * M grid. Some of the cells are empty, while others are occupied by the wall. Of course the robot can't move into the wall, and it can't move outside the grid too. The robot can only accept three commands: TURN LEFT, TURN RIGHT and GO. The robot may face to North, South, East or West during the movement. When it receives a TURN LEFT command, it will rotate 90 degree to the left. That is, if it faces to east before the command, it will face to north after the TURN LEFT command. The TURN RIGHT command is almost the same, except that the direction is opposite. When receiving the GO command, the robot will move 1 unit towards its orientation, unless there is a nonempty cell in front of it.

You want to use minimum number of instructions, so you should write a program for help.

Please note the robot is always faces to north at the beginning, i.e., face to the upper border in the maze map. (The maze map will be described below.)

Input

The first line of the input contains an integer T (T ≤ 15), indicating the number of test cases. Then T cases follow.

The first line of each test case contains two integers N and M, indicating the size of the maze. Then N lines followed, each line contains exactly M characters, describing the maze. The '#' indicates the wall, the '.' indicates the empty cell, the 'S' and 'T' indicate the start point and the destination of the robot respectively. There are no other characters in the maze map.

The orientation of the maze map is just the same as the common sense. That is, the upper-left corner of the maze map indicates the north-west direction, and the lower-right corner indicates the south-east.

You can assume 1 ≤ M ≤ 100 and 1 ≤ N ≤ 100. There is exactly one 'S' and one 'T' in the maze.

Output

Output one line for each test case, indicating the minimum number of instructions needed, or output -1 if it's impossible to reach the robot's destination.

Sample Input

2
5 5
#####
#...#
#.#.#
#S#T#
#####
4 5
#.#.#
#.#.#
#S#T#
#####

Sample Output

8
-1

Hint

The best instruction sequence for the first sample test case should be: GO, GO, TURN RIGHT, GO, GO, TURN RIGHT, GO, GO. And the length is 8.

Source

“开启时代杯”湘潭市第二届大学生程序设计大赛 (Internet)

  这个题目,没什么好说的,赤裸裸的广度优先搜索,直接上代码。

  C++源代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>

using namespace std;

#define MAX_LENGTH 101

typedef int COUNT;

// 用枚举型变量,分别规定N(北)、E(东)、S(南)、W(西)四个方向
typedef enum { N=1, E=2, S=4, W=8 } DIRECTION;

// 这个结构体,定义一个点的坐标,走了的步数,和当前方向
typedef struct { int x, y, step; DIRECTION dir; } COOR;

int rows, cols;
char maze[MAX_LENGTH][MAX_LENGTH];

inline bool isEnd ( COOR cur )
{
    if ( maze[cur.x][cur.y] == 'T' ) // 判断到终点了没有
        return true;   // 到达返回true
    else
        return false;  // 未到达返回false
}

int BFS( COOR start )  // 广度优先搜索
{
    COOR present, next; // 当前位置和下一个位置
    queue<COOR>routine; // 路线队列
    routine.push(start);
    maze[start.x][start.y] = N;
    while ( !routine.empty() ) // 当队列不为空时
    {
        // 出队
        present = routine.front(); // 队头元素赋值给present
        routine.pop();    // 删除队头元素


        next.step = present.step + 1; // 步数加一

        // 坐标处理
        next.x = present.x;
        next.y = present.y;

        if ( present.dir == N )  // 当前朝向为“北”
        {
            // 向左转
            next.dir = W;  // 转到西面

            // 此点面向西面是否已经经历过?若未经历过,则经历一下
            if( !(maze[next.x][next.y] & next.dir) )
            { // 开始经历
                // 入队
                routine.push(next);
                // 标记此点面向西面已经经历过
                maze[next.x][next.y] |= next.dir;
            }


            // 向右转
            next.dir = E;  // 转到东面

            // 此点面向东面是否已经经历过?若未经历过,则经历一下
            if( !(maze[next.x][next.y] & next.dir) )
            { // 开始经历
                // 入队
                routine.push(next);
                // 标记此点面东面已经经历过
                maze[next.x][next.y] |= next.dir;
            }
            // 向前走
            next.dir = N; // 面向北面
            next.x = present.x - 1; // 坐标处理
            if ( next.x >= 0 )
            {
                next.y = present.y;  // 坐标处理
                if ( isEnd(next) )  // 如果到终点
                    return next.step;  // 返回步数
                if ( maze[next.x][next.y] == '\0' )  // 若过没到过
                {
                    maze[next.x][next.y] = next.dir;  // 标记此点到过,方向向北
                    routine.push(next);  // 入队
                }
            }
        }
        else if ( present.dir == E )  // 当前朝向为“东”
        {
            // left
            next.dir = N;
            if( !(maze[next.x][next.y] & next.dir) )
            {
                routine.push(next);
                maze[next.x][next.y] |= next.dir;
            }
            // right
            next.dir = S;
            if( !(maze[next.x][next.y] & next.dir) )
            {
                routine.push(next);
                maze[next.x][next.y] |= next.dir;
            }
            // go
            next.dir = E;
            next.y = present.y + 1;
            if ( next.y < cols )
            {
                next.x = present.x;
                if ( isEnd(next) )
                    return next.step;
                if ( maze[next.x][next.y] == '\0' )
                {
                    routine.push(next);
                    maze[next.x][next.y] = next.dir;
                }
            }
        }
        else if ( present.dir == S )  // 当前朝向为“南”
        {
            // left
            next.dir = E;
            if( !(maze[next.x][next.y] & next.dir) )
            {
                routine.push(next);
                maze[next.x][next.y] |= next.dir;
            }
            // right
            next.dir = W;
            if( !(maze[next.x][next.y] & next.dir) )
            {
                routine.push(next);
                maze[next.x][next.y] |= next.dir;
            }
            // go
            next.dir = S;
            next.x = present.x + 1;
            if ( next.x < rows )
            {
                next.y = present.y;
                if ( isEnd(next) )
                    return next.step;
                if ( maze[next.x][next.y] == '\0' )
                {
                    routine.push(next);
                    maze[next.x][next.y] = next.dir;
                }
            }
        }
        else if ( present.dir == W )  // 当前朝向为“西”
        {
            // left
            next.dir = S;
            if( !(maze[next.x][next.y] & next.dir) )
            {
                routine.push(next);
                maze[next.x][next.y] |= next.dir;
            }
            // right
            next.dir = N;
            if( !(maze[next.x][next.y] & next.dir) )
            {
                routine.push(next);
                maze[next.x][next.y] |= next.dir;
            }
            // go
            next.dir = W;
            next.y = present.y - 1;
            if ( next.y >= 0 )
            {
                next.x = present.x;
                if ( isEnd(next) )
                    return next.step;
                if ( maze[next.x][next.y] == '\0' )
                {
                    routine.push(next);
                    maze[next.x][next.y] = next.dir;
                }
            }
        }
    }
    return -1;
}

int main (void)
{
    int n;
    COUNT i, j;
    COOR start;
    scanf( "%d", &n );
    while ( n -- )
    {
        scanf( "%d%d", &rows, &cols );
        gets(maze[0]);
        for ( i = 0 ; i < rows ; i ++ )
        {
            gets(maze[i]);
            for ( j = 0 ; j < cols ; j ++ )
            {
                if (maze[i][j] == 'S' )
                {
                    // 查找起点,并记录
                    start.x = i;
                    start.y = j;
                    start.step = 0;
                    start.dir = N;
                }
                else if ( maze[i][j] == '.' )
                    maze[i][j] = '\0'; // 可行点赋值'\0'
            }
        }
        printf( "%d\n", BFS( start ) );
    }
    return EXIT_SUCCESS;
}
posted @ 2012-08-05 21:14  叶剑飞Victor  阅读(391)  评论(0编辑  收藏  举报