测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A27701. 格子游戏

填空题 困难

题目描述

格子游戏

题目描述

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; #define N 40005 int fa[N], n, m; int getNum(int x, int y)//用1个数字代表二维的坐标点 { return (x-1)*n + y; } void init(int n) { for(int i = 1; i <= n; ++i) fa[i] = i; } int find(int x) { if(x == fa[x]) return x; else return fa[x] = find(fa[x]); } void merge(int x, int y) { fa[find(x)] = find(y); } int main() { int x, y, i, f, t; char c; cin >> n >> m; init(n*n); for(i = 1; i <= m; ++i)//i:第几步 { cin >> x >> y >> c; f = getNum(x, y); if(c == 'D') t = getNum(x+1, y); else//c == 'R' t = getNum(x, y+1); if(find(f) == find(t)) break; else merge(f, t); } if(i <= m) cout << i; else cout << "draw"; return 0; }

答案解析

方法2:直接使用坐标作为并查集中的元素

#include<bits/stdc++.h>

using namespace std;

typedef pair<int, int> Pair;

map<Pair, Pair> fa;

Pair find(Pair x)

{

if(x == fa[x])

return x;

else

return fa[x] = find(fa[x]);

}

void merge(Pair x, Pair y)

{

fa[find(x)] = find(y);

}

int main()

{

Pair p, q;

int n, m, x, y;

char c;

cin >> n >> m;

for(int i = 1; i <= m; ++i)

{

cin >> x >> y >> c;

p = Pair(x, y);

if(c == 'D')

q = Pair(x+1, y);

else//c == 'R'

q = Pair(x, y+1);

if(fa.count(p) == 0)//如果不存在该点,则初始化

fa[p] = p;

if(fa.count(q) == 0)

fa[q] = q;

if(find(p) == find(q))//p, q已连通,p,q再连边,则存在环

{

cout << i;//输出步数

return 0;

}

merge(p, q);//合并两点

}

cout << "draw";

   return 0;

}

上一题 下一题