zoukankan      html  css  js  c++  java
  • [CF1344B] Monopole Magnets

    Description

    有一个 (n imes m) 的方格图,格子被染成了黑色或者白色。要在里面放一些单极磁铁,一个格子内可以放置多个磁铁。

    定义磁铁的吸引:如果 N 与 S 处在同一行/列中,那么 N 会向着 S 的方向移动一格。

    每行每列至少有一个 S。

    对于每个黑色格子,至少存在一个 N 使得经过一系列吸引操作可以经过它。

    对于每个白色格子,不存在任何一个 N 使得经过系列吸引操作可以经过它。

    求至少需要几个 N 磁铁。

    Solution

    对于每个黑色连通块,暴力把每个格子放上 S,那么这个连通块中只要放一个 N,这个连通块就 OK 了。

    一行/列中,不能存在两个不相邻的黑色块(因为每行每列至少有一个 S)。

    一个格子可以放 S,当且仅当它是黑,或者它所在行列均没有黑。同时我们要求每行每列都至少有一个 S,因此还需要根据这个条件检验一下。

    综上所述,我们首先判断每行/列中是否存在两个不相邻的黑块,然后判断对于每行每列是否都至少存在一个位置满足它是黑,或者它所在行列均没有黑。如果成立,那么我们输出黑色连通块的个数即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    int main()
    {
        int n, m;
        cin >> n >> m;
    
        vector<vector<int>> a(n + 2);
        for (auto &i : a)
            i.resize(m + 2);
    
        vector<vector<int>> b(n + 2);
        for (auto &i : b)
            i.resize(m + 2);
    
        vector<vector<int>> vis(n + 2);
        for (auto &i : vis)
            i.resize(m + 2);
    
        for (int i = 1; i <= n; i++)
        {
            string tmp;
            cin >> tmp;
            for (int j = 1; j <= m; j++)
            {
                char ch = tmp[j - 1];
                if (ch == '#')
                    a[i][j] = 0;
                else
                    a[i][j] = 1;
            }
        }
    
        for (int i = 1; i <= n; i++)
        {
            vector<int> tmp;
            for (int j = 1; j <= m; j++)
            {
                if (a[i][j] == 0)
                    tmp.push_back(j);
            }
            for (int j = 1; j < tmp.size(); j++)
            {
                if (tmp[j] != tmp[j - 1] + 1)
                {
                    cout << -1 << endl;
                    return 0;
                }
            }
        }
    
        for (int j = 1; j <= m; j++)
        {
            vector<int> tmp;
            for (int i = 1; i <= n; i++)
            {
                if (a[i][j] == 0)
                    tmp.push_back(i);
            }
            for (int i = 1; i < tmp.size(); i++)
            {
                if (tmp[i] != tmp[i - 1] + 1)
                {
                    cout << -1 << endl;
                    return 0;
                }
            }
        }
    
    
        vector<int> blackcount_row(n + 2);
        vector<int> blackcount_col(m + 2);
    
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                if (a[i][j])
                    continue;
                blackcount_row[i]++;
                blackcount_col[j]++;
            }
        }
    
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                if (a[i][j] == 0 || (blackcount_row[i] == 0 && blackcount_col[j] == 0))
                {
                    b[i][j] = 1;
                }
            }
        }
    
        for (int i = 1; i <= n; i++)
        {
            int cnt = 0;
            for (int j = 1; j <= m; j++)
                cnt += b[i][j];
            if (cnt == 0)
            {
                cout << -1 << endl;
                return 0;
            }
        }
    
        for (int j = 1; j <= m; j++)
        {
            int cnt = 0;
            for (int i = 1; i <= n; i++)
            {
                cnt += b[i][j];
            }
            if (cnt == 0)
            {
                cout << -1 << endl;
                return 0;
            }
        }
    
        auto check = [n, m](int i, int j) -> bool {
            return i >= 1 && j >= 1 && i <= n && j <= m;
        };
    
        function<void(int, int)> dfs = [&](int i, int j) {
            static const int dx[] = {1, -1, 0, 0};
            static const int dy[] = {0, 0, 1, -1};
    
            vis[i][j] = 1;
    
            for (int d = 0; d < 4; d++)
            {
                int ni = i + dx[d];
                int nj = j + dy[d];
                if (check(ni, nj) && vis[ni][nj] == 0 && a[i][j] == 0)
                {
                    dfs(ni, nj);
                }
            }
        };
    
        int cnt = 0;
    
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                if (a[i][j] == 0 && vis[i][j] == 0)
                {
                    dfs(i, j);
                    ++cnt;
                }
            }
        }
    
        cout << cnt << endl;
    }
    
  • 相关阅读:
    第12课
    第11课
    第6课
    第5课
    ubuntu apache 通过端口新建多个站点
    phpstudy所需运行库
    ubuntu 修改和配置ip
    Linux Cp命令
    Ubuntu各个版本的镜像下载地址
    ubuntu 虚拟机添加多个站点
  • 原文地址:https://www.cnblogs.com/mollnn/p/14085777.html
Copyright © 2011-2022 走看看