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;
}
浙公网安备 33010602011771号