poj 3083 children of the candy corn----DFS 和BFS (蛋疼的方向)
2012-03-08 13:52 java环境变量 阅读(427) 评论(0) 编辑 收藏 举报 Children of the Candy Corn
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 6047 | Accepted: 2637 |
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.
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.
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
/* 这题那个左右方向 搞了我一晚上...今天再来调试了一遍终于发现了错误的原因,终于AC了. 一步一步的调试了很多遍,基本上每个语句都在脑袋里运行了几遍才AC.但收获还是很大的. 题目大意 : "."表示路,"#"表示墙壁。 分别求出优先左转,优先右转 的步数 和最短 的路径 所需步数。 'S'代表起点 'E'代表终点。 最短路用BFS 那个左右方向的问题,可以定一个坐标方向,每次通过上个点来的方向判断. 用dfs深搜 一直到终点统计步数即可。 思路 在代码注释中。 */ //Memory: 192 KB Time: 0 MS //Language: C++ Result: Accepted #include<stdio.h> #include<string.h> int left_dfs(int m,int count); //count 用于统计步数 int right_dfs(int m,int count); int bfs(int m); int vir[40*40],fa[40*40],fa_dir[40*40]; char maze[40][40]; int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; //方向很重要。解题关键,也是最蛋疼的地方 int q[40*40]; int w,h,start,end; int main() { //freopen("1.txt","r",stdin); int n,i,j; while(scanf("%d",&n)!=EOF) { while(n--) { memset(vir,0,sizeof(vir)); scanf("%d%d",&w,&h); for(i=0;i<h;i++) { scanf("%s",maze[i]); for(j=0;j<w;j++) { if(maze[i][j]=='S') start=i*w+j; //记下起点 if(maze[i][j]=='E') end=i*w+j; //记下终点 } } printf("%d %d %d\n",left_dfs(start,1),right_dfs(start,1),bfs(start)); } } return 0; } int left_dfs(int m,int count) { int x=m/w,y=m%w; int k,i=(fa_dir[m]+3)%4; //方向从上一个点来的方向的左边开始 for(k=1;k<=4;i=(i+1)%4,k++) //向右转,检验。(昨晚就是因为向左转错的) { int nx=x+dir[i][0]; int ny=y+dir[i][1]; int z=nx*w+ny; if(z==end) return count+1; if(maze[nx][ny]=='.') //如果可行 { fa_dir[z]=i; //记下方向 return left_dfs(z,count+1); //递归搜索,同时计数。 } } return 0; } int right_dfs(int m,int count) { int x=m/w,y=m%w; int k,i=(fa_dir[m]+1)%4; //方向从上一个点来的方向的右边开始 for(k=1;k<=4;i=(i+3)%4,k++) //思路与左转的函数一样 { int nx=x+dir[i][0]; int ny=y+dir[i][1]; int z=nx*w+ny; if(z==end) return count+1; if(maze[nx][ny]=='.') { fa_dir[z]=i; return right_dfs(z,count+1); } } return 0; } //bfs求最短路 int bfs(int m) { int count=0,front=0,rear=0,i,z,ok=0; q[rear++]=m; //第一个元素入队 vir[m]=1; fa[m]=m; while(front<rear) //队列非空 { m=q[front++]; //首元素出队 int x=m/w,y=m%w; for(i=0;i<4;i++) //考虑子方向 { int nx=x+dir[i][0]; int ny=y+dir[i][1]; z=nx*w+ny; if(maze[nx][ny]=='.'&&!vir[z]&&nx>=0&&nx<h&&ny>=0&&ny<w) //可行 { q[rear++]=z; //入队 fa[z]=m; //记下父元素 vir[z]=1; //标记已搜 } if(maze[nx][ny]=='E') //终点 { fa[z]=m; ok=1; break; } } if(ok) break; } z=end; while(fa[z]!=z) //求出步数 { count++; z=fa[z]; } return count+1; }
ps: 以后的题都会写 题目大意,