中南大学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
10ESample 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; }