本题的类型我一看就想到使用并查集解了,因为要查找是否有环,这是并查集的典型用法。
但是由于本题数据实在是太水了,故此有人使用直接模拟都过了。这让本题降了个档次。
这里使用并查集解。而且可以根据需要简化并查集函数,代码还是很好打的。
#include <stdio.h> #include <vector> #include <string.h> #include <algorithm> #include <iostream> #include <string> #include <limits.h> #include <stack> #include <queue> #include <set> #include <map> using namespace std; const int MAX_N = 11; const int MAX_V = MAX_N * MAX_N; struct Subset { int step, p; }; Subset sub[MAX_V]; char Maze[MAX_N][MAX_N]; int R, C, sx = 0, sy; int findPar(int x) { if (sub[x].p) return sub[x].p = findPar(sub[x].p); return x; } inline void unionTwo(int x, int p) { sub[x].p = p; } inline bool isLegal(int r, int c) { return 0<=r && 0 <= c && r<R && c<C; } bool exitMaze(int &out, int &loop) { int step = 0, si = sx, sj = sy, sni, snj; memset(sub, 0, sizeof(Subset)*(R*C+1)); while (true) { step++; int p = si * C + sj + 1;//注意下标0不使用,作为空标志 sub[p].step = step; //下一个格 if (Maze[si][sj] == 'S') { sni = si+1, snj = sj; } else if (Maze[si][sj] == 'W') { sni = si, snj = sj-1; } else if (Maze[si][sj] == 'E') { sni = si, snj = sj+1; } else { sni = si-1, snj = sj; } if (!isLegal(sni, snj))//out of one side of Maze { out = step; return true; } int son = sni * C + snj + 1;//注意0不使用 int pf = findPar(p); int sonf = findPar(son); if (pf == sonf) { out = sub[son].step-1; loop = step - out; return false; } unionTwo(son, pf); si = sni, sj = snj; } } int main() { while (~scanf("%d %d %d", &R, &C, &sy) && R) { getchar(); for (int i = 0; i < R; i++) { gets(Maze[i]); } sy--; int out = 0, loop = 0; if (exitMaze(out, loop)) { printf("%d step(s) to exit\n", out); } else { printf("%d step(s) before a loop of %d step(s)\n", out, loop); } } return 0; }
HDU 1035 Robot Motion Union Find 并查集题解
时间: 2024-10-13 21:02:21