中南大学2012暑期集训中期检测训练赛“跳跳”解题报告

  中南大学2012暑期集训中期检测训练赛,第H题,跳跳(题目链接)。

跳跳

Description

  一个每块地板标记着0~9某个数字的迷宫,其中标记1的地板不可以走,标记2~9的地板可以不花时间地跳到任意相同数字的位置,也可以和标记0的地板一样向前后左右任意方向花1个单位时间移动1的距离。给出起点和终点,求起点到终点的最短时间。

Input

  每组数据第一行一个n,表示尺寸,2 ≤ n ≤ 100。
  接下来n行每行n个0~9的字符,或S表示起点,E表示终点,S和E的运动规则与0相同。整个地图只有一个S和一个E。

Output

  每组数据输出一个数,占一行,表示起点到终点可以花费的最短时间。
  如果无法到达重点,输出“Oh No!”

Sample Input

5
0S100
00131
00300
00000
003E0
3
S12
010
10E

Sample Output

4
Oh No!

  题意:输入迷宫的值。S为起点,可上下左右走一步,费时为1。E为终点。值为1的点禁止通行。值为2~9的点可以不花时间飞跃到相同值的点,也可上下左右走一步,每步费时为1。值为0的点可上下左右行走一步,每步费时1。求起点到终点至少费时多少。

  解题思路:广度优先搜索。每次遇到0或2~9,就判断耗费时间是否小于这里耗费的时间的暂时最小值,如果小于则替换暂时最小值并判断是否为2~9,如果是,则刷新相同值的全部点。如此往复,直到终点。

  C++源代码如下:

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

using namespace std;

#define MAX_LENGTH 101

typedef int COUNT;
typedef struct { int x, y, time; } COOR;

char maze[MAX_LENGTH][MAX_LENGTH];
char minMat[MAX_LENGTH][MAX_LENGTH];
vector<COOR> sameCoor[10];

bool visit( queue<COOR> &Q, const int x, const int y, const int time, const int n )
{
    COOR next;
    if ( x >= 0 && x < n && y >= 0 && y < n )
    {
        if ( maze[x][y] == 'S' )
            return false;
        if ( maze[x][y] == 'E' )
            return true;
        else if ( maze[x][y] == '1' )
            return false;
        else
        {
            if ( time < minMat[x][y] )
            {
                minMat[x][y] = time;
                next.x = x;
                next.y = y;
                next.time = time;
                Q.push( next );
                if ( maze[x][y] != '0' )
                {
                    int num = maze[x][y] - '0';
                    for(vector<COOR>::iterator it = sameCoor[num].begin();
                            it != sameCoor[num].end(); it ++ )
                    {
                        next.x = it->x;
                        next.y = it->y;
                        next.time = time;
                        minMat[next.x][next.y] = time;
                        Q.push( next );
                    }
                }
            }
        }
    }
    return false;
}

int BFS( const COOR start, const int n )
{
    COOR current;
    queue<COOR> Q;

    memset( minMat, CHAR_MAX, sizeof(minMat) );
    Q.push(start);

    while ( !Q.empty() )
    {
        current = Q.front();
        Q.pop();

        // left
        if ( visit( Q, current.x - 1, current.y, 1 + current.time, n ) )
            return 1 + current.time;
        // right
        if ( visit( Q, current.x + 1, current.y, 1 + current.time, n ) )
            return 1 + current.time;
        // up
        if ( visit( Q, current.x, current.y - 1, 1 + current.time, n ) )
            return 1 + current.time;
        // down
        if ( visit( Q, current.x, current.y + 1, 1 + current.time, n ) )
            return 1 + current.time;
    }
    return -1;
}

int main (void)
{
    COUNT i, j;
    int n, step;
    COOR start;
    COOR current;
    while ( scanf( "%d", &n ) != EOF )
    {
        for ( i = 0 ; i < 10 ; i ++ )
            sameCoor[i].clear();
        for ( i = 0 ; i < n ; i ++ )
        {
            scanf( "%s", maze[i] );
            for ( j = 0 ; j < n ; j ++ )
            {
                current.x = i;
                current.y = j;
                current.time = 0;
                if ( maze[i][j] == 'S' )
                    start = current;
                else if ( maze[i][j] >= '0' && maze[i][j] <= '9' )
                    sameCoor[ maze[i][j]-'0' ].push_back( current );
            }
        }
        step = BFS( start, n );
        if ( step < 0 )
            printf( "Oh No!\n" );
        else
            printf( "%d\n", step );
    }
    return EXIT_SUCCESS;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值