1347:【例4-8】格子游戏
【题目描述】
Alice和Bob玩了一个古老的游戏:首先画一个n × n的点阵(下图n = 3)
接着,他们两个轮流在相邻的点之间画上红边和蓝边:
直到围成一个封闭的圈(面积不必为1)为止,“封圈”的那个人就是赢家。因为棋盘实在是太大了(n ≤ 200),他们的游戏实在是太长了!他们甚至在游戏中都不知道谁赢得了游戏。于是请你写一个程序,帮助他们计算他们是否结束了游戏?
【输入】
输入数据第一行为两个整数n和m。m表示一共画了m条线。以后m行,每行首先有两个数字(x, y),代表了画线的起点坐标,接着用空格隔开一个字符,假如字符是"D ",则是向下连一条边,如果是"R "就是向右连一条边。输入数据不会有重复的边且保证正确。
【输出】
输出一行:在第几步的时候结束。假如m步之后也没有结束,则输出一行“draw”。
【输入样例】
3 5 1 1 D 1 1 R 1 2 D 2 1 R 2 2 D
【输出样例】
4
#include <bits/stdc++.h> using namespace std; struct UnionFind { vector<int> b; // boss UnionFind(int n) { // boss[i] = {i} b = vector<int>(n); for (int i = 0; i < n; i++) { b[i] = i; } // Show(); } int Find(int i) { // 查找i的老板 if (b[i] != i) { b[i] = Find(b[i]); } return b[i]; } void Union(int i, int j) { // 将i和j归为同一个老板 int bi = Find(i); int bj = Find(j); if (bi != bj) { b[bi] = bj; } // Show(); } bool IsOne(int i, int j) { // 查看i和j是否同一个老板 int bi = Find(i); int bj = Find(j); return (bi == bj); } void Show() { // 调试时使用 for (int i = 0; i < b.size(); i++) { cout << b[i] << " "; } cout << endl; } }; void f(int &a, int &b, int ch) { switch (ch) { case 'D': a += 1; break; case 'R': b += 1; break; case 'U': a -= 1; break; case 'L': b -= 1; break; } } int main() { // freopen("1.txt", "r", stdin); int n, m; scanf("%d%d", &n, &m); UnionFind uf(n * n); int a, b; char ch; for (int i = 0; i < m; i++) { cin >> a >> b >> ch; int d1 = (a - 1) * n + (b - 1); f(a, b, ch); int d2 = (a - 1) * n + (b - 1); if (uf.IsOne(d1, d2)) { cout << (i + 1); return 0; } else { uf.Union(d1, d2); } } cout << "draw"; return 0; }