AcWing算法提高课-4.1.1格子游戏

算法提高课整理

CSDN个人主页:更好的阅读体验

Start

原题链接
题目描述

Alice 和 Bob 玩了一个古老的游戏:首先画一个 n × n n \times n n×n 的点阵(下图 n = 3 n = 3 n=3 )。

接着,他们两个轮流在相邻的点之间画上红边和蓝边:

1.png

直到围成一个封闭的圈(面积不必为 1 1 1)为止,“封圈”的那个人就是赢家。因为棋盘实在是太大了,他们的游戏实在是太长了!

他们甚至在游戏中都不知道谁赢得了游戏。

于是请你写一个程序,帮助他们计算他们是否结束了游戏?

输入格式

输入数据第一行为两个整数 n n n m m m n n n表示点阵的大小, m m m 表示一共画了 m m m 条线。

以后 m m m 行,每行首先有两个数字 ( x , y ) (x, y) (x,y),代表了画线的起点坐标,接着用空格隔开一个字符,假如字符是 D D D,则是向下连一条边,如果是 R R R 就是向右连一条边。

输入数据不会有重复的边且保证正确。

输出格式

输出一行:在第几步的时候结束。

假如 m m m 步之后也没有结束,则输出一行 draw

数据范围

1 ≤ n ≤ 200 1 \le n \le 200 1n200
1 ≤ m ≤ 24000 1 \le m \le 24000 1m24000

输入样例:
3 5
1 1 D
1 1 R
1 2 D
2 1 R
2 2 D
输出样例:
4

思路

要判断是否成环。注意到如果最终成环,那么最后一次连接的时候两个端点在同一个连通块内。

对于连通块的问题,我们使用并查集解决。

问题解答
  • Q:二维的网格如何放到并查集中?
  • A:一种 trick,对于每个点 ( x , y ) (x,y) (x,y) 建立映射 f ( x , y ) = x × n + y f(x,y)=x\times n+y f(x,y)=x×n+y 即可。这样就建立了一个 0 ∼ n × n − 1 0 \sim n \times n - 1 0n×n1 的映射关系。
算法时间复杂度

m m m 轮操作,并查集均摊复杂度 O ( α ) O(\alpha) O(α),因此这一步 O ( α m ) O(\alpha m) O(αm)

不过考虑到并查集的初始化复杂度为 O ( n 2 ) O(n^2) O(n2),因此预处理是瓶颈。

总复杂度 O ( n 2 ) O(n^2) O(n2)

AC Code

C + + \text{C}++ C++

#include <iostream>

using namespace std;

const int N = 210;

int n, m;
int p[N * N];

int get(int x, int y)
{
    return x * n + y;
}

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    scanf("%d%d", &n, &m);

    for (int i = 0; i < n * n; i ++ )
        p[i] = i;

    char op;
    int x, y, r1, r2;
    for (int i = 1; i <= m; i ++ )
    {
        cin >> x >> y >> op;
        x -- , y -- ;
        int r1 = get(x, y);
        if (op == 'D') r2 = get(x + 1, y);
        else r2 = get(x, y + 1);

        r1 = find(r1), r2 = find(r2);
        if (r1 == r2)
        {
            printf("%d\n", i);
            exit(0);
        }
        p[r1] = r2;
    }
    puts("draw");

    return 0;
}

228aa7bed3e021faf24cf8560d3e47bb.gif

最后,如果觉得对您有帮助的话,点个赞再走吧!

  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星河依旧长明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值