POJ3083 Children of the Candy Corn(靠墙走dfs+任意走bfs)

                                              Children of the Candy Corn

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 16527   Accepted: 7062

Description

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

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.

Output

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.

Sample Input

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

Sample Output

37 5 5
17 17 9

这是一个奇怪的迷宫,迷宫的入口和出口都在边上,不可能在角落里

题目大意等同于  迷宫里面漆黑,你什么都看不到,只能扶着墙走,你可以选择扶一直左边的墙或一直扶右边的墙,问你扶左边的墙到出口的距离、扶右边的墙到出口的距离和实际上入口到出口的最短距离(不一定是扶墙走的二者之一)

这里的距离包括入口o

扶着墙走还是挺困难的,因为面对着不同的方向,你需要转弯的顺序就不一样,下面的图简单的表示了当我们面向东的时候我们可能的转弯顺序是怎么样的,仔细想想就是这样,面向其他方向可以依次类推,因此我们使用dfs枚举方向的时候需要注意枚举的顺序,前提是我们必须明确在某一个位置的时候,所谓的前面是什么方向。

   
西

→左:北-西-南-东(逆时针)

→右:南-西-北-东(顺时针)

   

因为扶着墙走有可能会走到死胡同,还要按原路返回,所以并不是路径只能走一遍

两个dfs完全可以合并 合并是16ms,分开就是0ms了

实际的最短距离,简单的bfs就OK了

很惨的就是为什么结构体的构造函数在G++编译器上就是WA!!!!!!害人不浅啊

                           

#include<cstdio>
#include<string>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int _read() {
    char ch = getchar();
    int sum = 0;
    while (!(ch >= '0' && ch <= '9'))ch = getchar();
    while (ch >= '0' && ch <= '9')sum = sum * 10 + ch - 48, ch = getchar();
    return sum;
}
const int inf=0x3f3f3f3f;
const int mm=44;

char mp[mm][mm];
int n,m;
int sx,sy,ex,ey;
int to[4][2]={0,1,1,0,0,-1,-1,0};//e s w n四个方向 有顺序  

int dfs_l(int x,int y,int dir){
	if(x==ex&&y==ey)
		return 1;
	for(int i=dir-1;i<=dir+2;i++){//逆时针  
		int ndir=(i+4)%4;
		int nx=x+to[ndir][0];
		int ny=y+to[ndir][1];
		if(nx<0||nx>=n||ny<0||ny>=m||mp[nx][ny]=='#')
			continue;
		return dfs_l(nx,ny,ndir)+1;
	}
}	
	
int dfs_r(int x,int y,int dir){	
	if(x==ex&&y==ey)
		return 1;
	for(int i=dir+1;i>=dir-2;i--){//顺时针  
		int ndir=(i+4)%4;
		int nx=x+to[ndir][0];
		int ny=y+to[ndir][1];
		if(nx<0||nx>=n||ny<0||ny>=m||mp[nx][ny]=='#')
			continue;
		return dfs_r(nx,ny,ndir)+1;
	}
}

struct node{
	int x,y;
	int step;
	node(int a,int b,int c):x(a),y(b),step(c){}
};
int bfs(){
	queue<node>q;
	q.push(node(sx,sy,0));
	mp[sx][sy]='#';
	while(!q.empty()){
		node pre=q.front();
		q.pop();
		for(int i=0;i<4;i++){
			int nx=pre.x+to[i][0];
			int ny=pre.y+to[i][1];
			if(nx<0||nx>=n||ny<0||ny>=m||mp[nx][ny]=='#')
				continue;
			if(nx==ex&&ny==ey)
				return pre.step+1;
			mp[nx][ny]='#';
			q.push(node(nx,ny,pre.step+1));
		}
	}
}

int main()
{
	int t;
	cin>>t;
	while(t--){
		scanf("%d%d",&m,&n);//
		for(int i=0;i<n;i++){
			scanf("%s",mp[i]);
			for(int j=0;j<m;j++)
				if(mp[i][j]=='S')
					sx=i,sy=j;
				else if(mp[i][j]=='E')
					ex=i,ey=j;
		}
		int dir;//确定初始方向  
		if(sx==0)
			dir=1;//s
		else if(sx==n-1)
			dir=3;//n
		else if(sy==0)
			dir=0;//e
		else 
			dir=2;//w
		int left=dfs_l(sx,sy,dir);
		int right=dfs_r(sx,sy,dir); 
		int minn=bfs()+1;
		printf("%d %d %d\n",left,right,minn);
	}	
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章