POJ 3083 Children of the Candy Corn

来源:互联网 发布:高性能网络编程 二 编辑:程序博客网 时间:2024/05/17 03:42

链接:http://poj.org/problem?id=3083

题目:

Language:
Children of the Candy Corn
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 8973 Accepted: 3913

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

28 8#########......##.####.##.####.##.####.##.####.##...#..##S#E####9 5##########.#.#.#.#S.......E#.#.#.#.##########

Sample Output

37 5 517 17 9

解题思路:

这条题目是一个迷宫类的搜索的问题。我们可以把它分解成两个子问题,一个是沿某个特定的方向搜索达到终点的步数dfs(),一个是搜索起点到终点的最短路bfs()。这里的bfs没什么要说的,关键就是这个dfs,与我们之前遇到的dfs()不同。



我们可以利用这样一张图,来构建一个模型。五角星的位置是你当前所在的位置。沿着左边走的时候,如果是走到1位置,下次要前往2位置,如果2可以走的话,就走到2位置,否则就前往1位置,如果1位置可以走的话,就走到1位置,否则就前往0位置,否则就前往1位置,总而言之,就是按照顺时针的方向走一遍。

d = 0 时,下一步的位置序列: 1  0  3  2

d = 1 时,下一步的位置序列: 2  1  0  3

d = 2时,下一步的位置序列:  3  2  1  0

d = 3时,下一步的位置序列:  0  3  2  1

通过观察,我们可以发现,下一步d的位置序列为 (d + dir[i]) % 4,其中dir[] = {1, 0, 3, 2},这样的话我们就可以用dfs(int x, int y, int dir)来表示当前的状态了, 里面的状态转移也可以表示出来了。沿着右边走是按照逆时针方向走。

感觉这道题目比较好,把dfs和bfs放到了一起,可以加深我们对dfs和bfs的理解。


代码:

#include <iostream>#include <cstdio>#include <queue>#include <cstring>using namespace std;const int MAXN = 45;char map[MAXN][MAXN];int vis[MAXN][MAXN];int w, h, d, sx, sy, flag, shortest;int dx[] = {-1,  0,  1,  0};int dy[] = { 0, -1,  0,  1};int dd[4][4] = {0,  0,  0,  0,1,  0,  3,  2,0,  0,  0,  0,3,  0,  1,  2};struct Point{int x, y, cur;};int dfs(int x, int y, int dir, int m){if('E' == map[x][y]) return 1;for(int i = 0; i < 4; i++){int di = (dir + dd[m][i]) % 4;int xx = x + dx[di], yy = y + dy[di];if(xx >= 0 && xx < h && yy >= 0 && yy < w && '#' != map[xx][yy]){//printf("%d %d %d\n", xx, yy, di);return dfs(xx, yy, di, m) + 1;}}return 0;}int bfs(){queue<Point> q;Point p;p.x = sx, p.y = sy, p.cur = 1;q.push(p); while(!q.empty()){Point pp = q.front();q.pop();if('E' == map[pp.x][pp.y]) return pp.cur;if(vis[pp.x][pp.y]) continue;vis[pp.x][pp.y] = 1;for(int i = 0; i < 4; i++){int x = pp.x + dx[i], y = pp.y + dy[i];if(!vis[x][y] && x >= 0 && x < h && y >= 0 && y < w &&   '.' == map[x][y] || 'E' == map[x][y]){Point tmp;tmp.x = x; tmp.y = y; tmp.cur = pp.cur + 1;q.push(tmp);}}}return 0;}int main(){int t;scanf("%d", &t);while(t--){memset(map, 0, sizeof(map));memset(vis, 0, sizeof(vis));scanf("%d%d", &w, &h);getchar();for(int i = 0; i < h; i++){for(int j = 0; j < w; j++){scanf("%c", &map[i][j]);if('S' == map[i][j]){sx = i;sy = j;}}getchar();}if(0 == sx)     d = 0;if(h - 1 == sx) d = 2;if(0 == sy)     d = 1;if(w - 1 == sy) d = 3; printf("%d %d %d\n", dfs(sx, sy, d, 1), dfs(sx, sy, d, 3), bfs());}return 0;}


0 0
原创粉丝点击