POJ - 3083:Children of the Candy Corn

Children of the Candy Corn

来源:

标签:深度优先搜索、宽度优先搜索
参考资料:

相似题目:

题目

The cornfield maze is a popular Halloween treat. Visitors are shown the entrance and must wander through the maze facing zombies, chainsaw-wielding psychopaths, hippies, and other terrors on their quest to find the exit.
One popular maze-walking strategy guarantees that the visitor will eventually find the exit. Simply choose either the right or left wall, and follow it. Of course, there’s no guarantee which strategy (left or right) will be better, and the path taken is seldom the most efficient. (It also doesn’t work on mazes with exits that are not on the edge; those types of mazes are not represented in this problem.)
As the proprieter of a cornfield that is about to be converted into a maze, you’d like to have a computer program that can determine the left and right-hand paths along with the shortest path so that you can figure out which layout has the best chance of confounding visitors.

输入

Input to this problem will begin with a line containing a single integer n indicating the number of mazes. Each maze will consist of one line with a width, w, and height, h (3 <= w, h <= 40), followed by h lines of w characters each that represent the maze layout. Walls are represented by hash marks (’#’), empty space by periods (’.’), the start by an ‘S’ and the exit by an ‘E’.
Exactly one ‘S’ and one ‘E’ will be present in the maze, and they will always be located along one of the maze edges and never in a corner. The maze will be fully enclosed by walls (’#’), with the only openings being the ‘S’ and ‘E’. The ‘S’ and ‘E’ will also be separated by at least one wall (’#’).
You may assume that the maze exit is always reachable from the start point.

输出

For each maze in the input, output on a single line the number of (not necessarily unique) squares that a person would visit (including the ‘S’ and ‘E’) for (in order) the left, right, and shortest paths, separated by a single space each. Movement from one square to another is only allowed in the horizontal or vertical direction; movement along the diagonals is not allowed.

输入样例

2
8 8
########
#......#
#.####.#
#.####.#
#.####.#
#.####.#
#...#..#
#S#E####
9 5
#########
#.#.#.#.#
S.......E
#.#.#.#.#
#########

输出样例

37 5 5
17 17 9

解题思路

给定起点S,终点E(均在迷宫边缘,且不在角落),有3种方式走出迷宫:
1.一直靠左走
2.一直靠右走
3.直接找到最短路径
第1、2种方式可以利用深度优先搜索,第3种方式可以利用宽度优先搜索。
在做深度优先搜索时,以第一种方式举例,不同的前进方向有不同的搜索顺序:

前进方向 搜索顺序
← ↑ → ↓
↑ → ↓ ←
→ ↓ ← ↑
↓ ← ↑ →
可以找到规律,写出搜索顺序。此外,第二种方式可以利用第一种的思路,只不过从终点出发前往起点。

参考代码

#include
#include
#include
#define MAXN 42
using namespace std;
char maze[MAXN][MAXN];
int vis[MAXN][MAXN];
int rows,cols;
int cnt;
int dx[4]={-1, 0, 1, 0},
    dy[4]={ 0, 1, 0,-1};
    
int getDir(int x, int y){//获取起始前进方向
	if(x==0)
		return 2;//south
	else if(x==rows-1)
		return 0;//north
	else if(y==0)
		return 1;//east
	else if(y==cols-1)
		return 3;//west
}

int dfs(int x,int y, int ex, int ey, int dir){
	cnt++;
	if(x==ex && y==ey){
		return 1;
	}
	for(int i=0;i<4;i++){
		int next_dir=(dir+3+i)%4;//搜索顺序
		int nx=x+dx[next_dir],
	        ny=y+dy[next_dir];
		if(maze[nx][ny]!='#'){
			if(dfs(nx,ny,ex,ey,next_dir))
				return 1;
		}
	}
}

int bfs(int x,int y,int ex,int ey){
	memset(vis,0,sizeof(vis));
	queue<int> qx,qy;
	qx.push(x);
	qy.push(y);
	vis[x][y]=1;
	while(!qx.empty()){
		x=qx.front(),
		y=qy.front();
		qx.pop();
		qy.pop();
		for(int i=0;i<4;i++){
			int nx=x+dx[i],
			    ny=y+dy[i];	
			if(0<=nx && nx<rows && 0<=ny && ny<cols && vis[nx][ny]==0){
				if(maze[nx][ny]=='#')continue;
				vis[nx][ny]=vis[x][y]+1;
				if(maze[nx][ny]=='E'){
					return 1;
				}
				qx.push(nx);
				qy.push(ny);	
			}	
		}
	}
}

int main(){
	int n;
	scanf("%d",&n);
	while(n--){
		scanf("%d%d",&cols,&rows);
		int sx,sy,ex,ey;
		char *t;
		for(int i=0;i<rows;i++){
			scanf("%s",maze[i]);
			if((t=strchr(maze[i],'S'))!=NULL){
				sx=i;
				sy=t-maze[i];
			}
			if((t=strchr(maze[i],'E'))!=NULL){
				ex=i;
				ey=t-maze[i];
			}
		}
		
		int dir;
		cnt=0;
		dir=getDir(sx,sy);
		dfs(sx,sy,ex,ey,dir);
		printf("%d ",cnt);
		
		cnt=0;
		dir=getDir(ex,ey);
		dfs(ex,ey,sx,sy,dir);//利用第一种思路,从终点出发前往起点
		printf("%d ",cnt);
		
		bfs(sx,sy,ex,ey);
		printf("%d\n",vis[ex][ey]);
	}
	return 0;
}

你可能感兴趣的:(【记录】算法题解)