Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=2364
这道题的特殊之处在于能转弯时不能直走,必须转弯,所以在行走时,要判断能否转弯,不能转弯时才选择直走。
因为是一道走迷宫的题,所以可以用BFS解决问题。
有一点需要注意:起点也有可能是终点,所以在判断是否到终点时,最好判断该点是不是'#',而不该判断是不是'.',因为终点有可能是'@'
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int NEVERCOME = -1;
const int NORTH = 0;
const int SOUTH = 2;
const int WEST = 1;
const int EAST = 3;
const int MAXN = 80 + 5;
int vis[MAXN][MAXN][5]; // the first param means x, the second one means y
// the third one means dir
char maze[MAXN][MAXN]; // record the maze
int moveToDir[4][2];
int Bfs( int height, int width, int startX, int startY );
bool isEnd( int &height, int &width, int &x, int &y ); // judge whether the person has reached the end point
bool isInside( int &height, int &width, int &x, int &y ); // judge whether the person has reached the end point
int main()
{
// dir
moveToDir[NORTH][0] = -1;
moveToDir[NORTH][1] = 0;
moveToDir[SOUTH][0] = 1;
moveToDir[SOUTH][1] = 0;
moveToDir[WEST][0] = 0;
moveToDir[WEST][1] = -1;
moveToDir[EAST][0] = 0;
moveToDir[EAST][1] = 1;
int T;
cin >> T;
int height, width;
int i, j;
int startX, startY;
while( T-- ) {
scanf( "%d%d", &height, &width );
for( i=0; i<height; i++ ) {
getchar();
for( j=0; j<width; j++ ) {
scanf( "%c", &maze[i][j] );
if( maze[i][j]=='@' ) {
startX = i;
startY = j;
}
//printf( "%c", maze[i][j] );
}
//printf("\n");
}
printf( "%d\n", Bfs( height, width, startX, startY ) );
}
return 0;
}
typedef struct Node{
int x, y;
int step;
int dir; // means the dir the person facing
}Node;
int Bfs( int height, int width, int startX, int startY ) {
queue <Node> q;
Node t, next;
t.x = startX;
t.y = startY;
t.step = 0;
memset( vis, NEVERCOME, sizeof(vis) );
int i, j;
// the four directions
t.dir = NORTH;
vis[t.x][t.y][t.dir] = 0;
q.push( t );
t.dir = SOUTH;
vis[t.x][t.y][t.dir] = 0;
q.push( t );
t.dir = WEST;
vis[t.x][t.y][t.dir] = 0;
q.push( t );
t.dir = EAST;
vis[t.x][t.y][t.dir] = 0;
q.push( t );
while( !q.empty() ) {
t = q.front();
q.pop();
if( isEnd( height, width, t.x, t.y ) ) {
return t.step;
}
int i;
bool flag = false;
// can the person go left or right
for( i=0; i<4;i++ ) {
if( (i&1) != ( t.dir&1 ) ) { // need to turn
next.x = t.x + moveToDir[i][0];
next.y = t.y + moveToDir[i][1];
next.step = t.step + 1;
next.dir = i;
if( isInside( height, width, next.x, next.y ) ) {
flag = true;
if( vis[next.x][next.y][next.dir]==-1 || next.step<vis[next.x][next.y][next.dir] ) {
q.push(next);
vis[next.x][next.y][next.dir] = next.step;
}
}
}
}
// should go straight ?
if( flag == false ) {
next.x = t.x + moveToDir[t.dir][0];
next.y = t.y + moveToDir[t.dir][1];
next.step = t.step + 1;
next.dir = t.dir;
if( isInside( height, width, next.x, next.y ) ) {
if( vis[next.x][next.y][next.dir]==-1 || next.step<vis[next.x][next.y][next.dir] ) {
q.push(next);
vis[next.x][next.y][next.dir] = next.step;
}
}
}
}
return -1;
}
bool isEnd( int &height, int &width, int &x, int &y ) {
if( maze[x][y] != '#' ) {
if( ( x==0 || x==height-1 ) || ( y==0 || y==width-1) ) {
return true;
}
}
return false;
}
bool isInside( int &height, int &width, int &x, int &y ) {
if( maze[x][y] == '.' ) {
if( x>=0 && x<height && y>=0 && y<width ) {
return true;
}
}
return false;
}