📜  门|门CS 2010 |第 51 题(1)

📅  最后修改于: 2023-12-03 15:42:22.444000             🧑  作者: Mango

介绍

本题是门电子竞技题,需要程序员使用数据结构和算法的知识进行解答。题目要求找到圆形阵营的总石头量,其中圆形阵营由相邻的小写字母组成一个连通块。

题目描述

给定一个只由大小写字母组成的矩阵,每个字母代表一个石头,大小写不同,代表不同的阵营。相邻的同字母石头组成一个连通块。其中所有小写字母石头组成的连通块代表圆形阵营。求圆形阵营中的石头总量,若无圆形阵营,则返回0。

输入格式

第一行输入两个整数,分别代表矩阵的长和宽。

随后的若干行代表矩阵的内容,其中大小写字母代表不同的石头。每个字母以一个空格隔开,行末无空格。

输出格式

输出一个整数,代表圆形阵营的石头总量。

数据范围

1 <= n,m <= 1000

代码示例

C++ 代码示例:

#include <iostream>
#include <vector>

using namespace std;

const int N = 1010;

int n, m;
char G[N][N];
bool st[N][N];

int dx[8] = {-1, -1, 0, 1, 1, 1, 0, -1}, dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};

void dfs(int x, int y, vector<pair<int, int>>& circle, int& cnt) {
    st[x][y] = true;
    circle.push_back({x, y});
    cnt++;
    for (int i = 0; i < 8; i++) {
        int nx = x + dx[i], ny = y + dy[i];
        if (nx < 0 || nx >= n || ny < 0 || ny >= m)
            continue;
        if (G[nx][ny] != G[x][y])
            continue;
        if (st[nx][ny])
            continue;
        dfs(nx, ny, circle, cnt);
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> G[i][j];
    int res = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (st[i][j])
                continue;
            if (isupper(G[i][j]))
                continue;
            vector<pair<int, int>> circle;
            int cnt = 0;
            dfs(i, j, circle, cnt);
            bool valid = true;
            for (auto [x, y]: circle)
                if (x <= 0 || x >= n - 1 || y <= 0 || y >= m - 1) {
                    valid = false;
                    break;
                }
            if (!valid)
                continue;
            for (auto [x, y]: circle)
                if (G[x - 1][y] == G[x + 1][y])
                    if (G[x][y - 1] == G[x][y + 1])
                        continue;
            res += cnt;
        }
    }
    cout << res << endl;
    return 0;
}

分析

该题可以通过深度优先搜索(DFS)实现。具体过程如下:

  • 遍历整个矩阵,找到所有未被标记的小写字母石头(表示一个圆形阵营)。
  • 对于每个圆形阵营,使用 DFS 找到其所有连通石头,同时统计其总量。
  • 判断该圆形阵营是否合法:若圆形阵营的任一部分紧贴矩阵边缘,或圆形阵营的边界处没有至少一块与其相邻的石头,则认为该圆形阵营不合法。
  • 对所有合法的圆形阵营石头量进行求和即可。

更详细的分析可以查看题解区。