题目:1250. 格子游戏 - AcWing题库
Alice和Bob玩了一个古老的游戏:首先画一个 n×n的点阵(下图 n=3)。
接着,他们两个轮流在相邻的点之间画上红边和蓝边:

直到围成一个封闭的圈(面积不必为 11)为止,“封圈”的那个人就是赢家。因为棋盘实在是太大了,他们的游戏实在是太长了!
他们甚至在游戏中都不知道谁赢得了游戏。
于是请你写一个程序,帮助他们计算他们是否结束了游戏?
输入格式
输入数据第一行为两个整数 n表示点阵的大小,m表示一共画了 m 条线。
以后 m 行,每行首先有两个数字 (x,y),代表了画线的起点坐标,接着用空格隔开一个字符,假如字符是 D,则是向下连一条边,如果是 R 就是向右连一条边。
输入数据不会有重复的边且保证正确。
输出格式
输出一行:在第几步的时候结束。
假如 m步之后也没有结束,则输出一行“draw”。
数据范围
1≤n≤200
1≤m≤24000
输入样例:
3 5
1 1 D
1 1 R
1 2 D
2 1 R
2 2 D
输出样例:
4
总结:
对于并查集来说,一维更加方便,故将2维数组转化为一维数组进行并查集的查找
转化方法:q[n][n]====>q[n*n]=x*n+y
条件:x,y,坐标必须从0开始
代码献上:(并查集--二维转一维)
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 40009;
int n, m, q[N],x,y;
int find(int x) //查找函数
{
return q[x] == x ? q[x] : q[x] = find(q[x]);
}
void merge(int x, int y) //合并操作函数
{
q[find(x)] = find(y);
}
void init() //并查集的初始化
{
for (int i = 1; i <= n * n; ++i) q[i] = i;
}
//维度的转化
int change(int a, int b) //2维转化为1维 一维的并查集方便
{ //条件:x,y坐标需要从0开始
return a * n + b;
}
int main()
{
cin >> n >> m;
init();
char c;
for (int i = 1, a, b; i <= m; ++i)
{
cin >> a >> b >> c; //注意这不是输入的点的坐标
a--, b--;
x = change(a, b);
if (c == 'D') y = change(a+1, b); //向下连边
else y = change(a, b+1) ; //向右连边
if (find(x) == find(y)) //如果在同一格子内
{
cout << i << endl;
return 0;
}
merge(x, y); //合并两个集合
}
cout << "draw" << endl;
return 0;
}
文章介绍了一个在n×n点阵上进行的两人游戏,玩家轮流画边,目标是形成封闭圈。程序需要判断在多少步后游戏结束或者是否结束。解决方案是通过将二维数组转化为一维并查集,实现查找和合并操作,检测是否存在环路来确定游戏状态。

被折叠的 条评论
为什么被折叠?



