POJ-3083 Children of the Candy Corn 恶心搜索
之前有听说如果在一个迷宫中一直沿着某一堵墙走的话,那么一定可以走出这个迷宫,这题讲的就是这个内容。这题的问法比较奇怪,问你沿着左边的墙,右边的墙走所花的时间和最少所花的时间。该题难点就在与如何让dfs的时候能够沿着墙走。其实是有规律的,那就是往左边走是顺时针方向dfs,往右走逆时针方向走dfs,每次要确定上一次来的方向,这样能够确定你第一次试探的方向是那个方向。例如:如果从最左边的墙进入的话,那么首先选择往上走,否则向前走,再否则向下走,最后还是没法走的话就向左走(往回走),走了之后就直接return,每次走了之后绝对不会再换方向搜索。这题竟然错在了手写的找最短路的队列上。
代码如下:
#include <cstring> #include <cstdlib> #include <cstdio> #include <queue> using namespace std; int N, M, sx, sy, visit[45][45]; int llen, rlen, slen, front, tail, dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0}; int ldir[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1}; int rdir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1}; int linitdir, rinitdir; char G[45][45]; struct Node { int x, y, s; }e[1000000], pos; bool judge(int x, int y) { if (x < 1 || x > N || y < 1 || y > M) { return false; } return true; } int bfs() { int xx, yy; front = 0; tail = 1; e[tail].x = sx, e[tail].y = sy; e[tail].s = 1; while (front != tail) { pos = e[++front]; for (int i = 0; i < 4; ++i) { xx = pos.x + dir[i][0], yy = pos.y + dir[i][1]; if (!visit[xx][yy] && judge(xx, yy)) { visit[xx][yy] = 1; if (G[xx][yy] == '.') { ++tail; e[tail].x = xx, e[tail].y = yy; e[tail].s = pos.s + 1; } else if (G[xx][yy] == 'E') { return pos.s + 1; } } } } } void getinitdir() { if (sy == 1) { linitdir = 0; rinitdir = 0; } else if (sx == 1) { linitdir = 1; rinitdir = 3; } else if (sy == M) { linitdir = 2; rinitdir = 2; } else { linitdir = 3; rinitdir = 1; } } int getslen() { memset(visit, 0, sizeof (visit)); visit[sx][sy] = 1; return bfs(); } int ldfs(int x, int y, int dd, int step) { for (int i = dd, j = 0; j < 4; ++i, ++j) { int k = i % 4; int xx = x + ldir[k][0], yy = y + ldir[k][1]; if (judge(xx, yy) && G[xx][yy] != '#') { if (G[xx][yy] == 'E') { return step + 1; } else if (G[xx][yy] == '.') { if (xx == x) { if (yy == y + 1) { k = 0; } else { k = 2; } } else { if (xx == x + 1) { k = 1; } else { k = 3; } } return ldfs(xx, yy, k, step+1); } } } } int rdfs(int x, int y, int dd, int step) { for (int i = dd, j = 0; j < 4; ++i, ++j) { int k = i % 4; int xx = x + rdir[k][0], yy = y + rdir[k][1]; if (judge(xx, yy) && G[xx][yy] != '#') { if (G[xx][yy] == 'E') { return step + 1; } else if (G[xx][yy] == '.') { if (xx == x) { if (yy == y + 1) { k = 0; } else { k = 2; } } else { if (xx == x+ 1) { k = 3; } else { k = 1; } } return rdfs(xx, yy, k, step+1); } } } } int main() { int T, flag; scanf("%d", &T); while (T--) { flag = 0; scanf("%d %d", &M, &N); for (int i = 1; i <= N; ++i) { scanf("%s", G[i]+1); for (int j = 1; !flag && j <= M; ++j) { if (G[i][j] == 'S') { sx = i, sy = j; flag = 1; } } } getinitdir(); slen = getslen(); llen = ldfs(sx, sy, linitdir, 1); rlen = rdfs(sx, sy, rinitdir, 1); printf("%d %d %d\n", llen, rlen, slen); } return 0; }