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;
}

 

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