• [CF1439A2] Binary Table (Hard Version)


    Description

    给定一个 (n imes m)(01) 矩阵,每次操作可以将某个 (2 imes2) 的矩阵内的 (3) 个数取反,请在 (n imes m) 步内将矩阵变为全 (0)

    Solution

    我们的基本思路是,任何一个 (2 imes 2) 的矩阵都可以经过不超过 (4) 次操作消去得到目标状态,因此对于任何一个边长为偶数的矩阵,我们只需要对于每个 (2 imes 2) 的小方块执行一次操作即可;对于一个边长为奇数的矩阵,我们先把它的最后一行(列)暴力消去,然后转化为偶数的情况进行处理。

    对于一个 (2 imes 2) 的方块的不超过四步操作,并且显然操作最多只会有 (4) 种,每种要么进行 (0) 次,要么进行 (1) 次,因此总共只有 (16) 种可能,暴力枚举这些可能即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    vector<pair<int, int>> s[2][2][2][2];
    
    bool check(int a00, int a01, int a10, int a11, int b00, int b01, int b10, int b11)
    {
        for (int i = 0; i < b00 + b01 + b10 + b11; i++)
        {
            a00 ^= 1;
            a01 ^= 1;
            a10 ^= 1;
            a11 ^= 1;
        }
        return ((a00 ^ b00) | (a01 ^ b01) | (a10 ^ b10) | (a11 ^ b11)) == 0;
    }
    
    void presolve(int a00, int a01, int a10, int a11)
    {
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < 2; j++)
            {
                for (int k = 0; k < 2; k++)
                {
                    for (int l = 0; l < 2; l++)
                    {
                        if (check(a00, a01, a10, a11, i, j, k, l))
                        {
                            if (i)
                                s[a00][a01][a10][a11].push_back({0, 1}),
                                    s[a00][a01][a10][a11].push_back({1, 1}),
                                    s[a00][a01][a10][a11].push_back({1, 0});
                            if (j)
                                s[a00][a01][a10][a11].push_back({0, 0}),
                                    s[a00][a01][a10][a11].push_back({1, 0}),
                                    s[a00][a01][a10][a11].push_back({1, 1});
                            if (k)
                                s[a00][a01][a10][a11].push_back({0, 1}),
                                    s[a00][a01][a10][a11].push_back({0, 0}),
                                    s[a00][a01][a10][a11].push_back({1, 1});
                            if (l)
                                s[a00][a01][a10][a11].push_back({0, 0}),
                                    s[a00][a01][a10][a11].push_back({0, 1}),
                                    s[a00][a01][a10][a11].push_back({1, 0});
                        }
                    }
                }
            }
        }
    }
    
    void presolve()
    {
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < 2; j++)
            {
                for (int k = 0; k < 2; k++)
                {
                    for (int l = 0; l < 2; l++)
                    {
                        presolve(i, j, k, l);
                    }
                }
            }
        }
    }
    
    vector<pair<int, int>> solve(int i, int j, vector<vector<int>> &a)
    {
        auto ans = s[a[i][j]][a[i][j + 1]][a[i + 1][j]][a[i + 1][j + 1]];
        for (auto &t : ans)
        {
            t.first += i;
            t.second += j;
        }
        return ans;
    }
    
    vector<pair<int, int>> bruteforce(int i, int j, vector<vector<int>> &a, int n, int m)
    {
        vector<pair<int, int>> ans;
        if (a[i][j])
        {
            if (i < n && j < m)
            {
                ans.push_back({0, 0});
                ans.push_back({0, 1});
                ans.push_back({1, 0});
            }
            else if (i < n)
            {
                ans.push_back({0, 0});
                ans.push_back({1, 0});
                ans.push_back({1, -1});
            }
            else
            {
                ans.push_back({0, 0});
                ans.push_back({0, 1});
                ans.push_back({-1, 1});
            }
        }
        for (auto &t : ans)
        {
            t.first += i;
            t.second += j;
        }
        for (auto t : ans)
        {
            a[t.first][t.second] ^= 1;
        }
        return ans;
    }
    
    void LinkToEnd(vector<pair<int, int>> &ans, vector<pair<int, int>> tmp)
    {
        ans.insert(ans.end(), tmp.begin(), tmp.end());
    }
    
    void solve()
    {
        int n, m;
        cin >> n >> m;
    
        vector<vector<int>> a(n + 2);
    
        for (int i = 1; i <= n; i++)
        {
            a[i].resize(m + 2);
        }
    
        for (int i = 1; i <= n; i++)
        {
            string tmp;
            cin >> tmp;
            for (int j = 1; j <= m; j++)
            {
                a[i][j] = tmp[j - 1] - '0';
            }
        }
    
        vector<pair<int, int>> ans;
    
        if (n & 1)
        {
            for (int j = 1; j <= m; j++)
            {
                LinkToEnd(ans, bruteforce(1, j, a, n, m));
            }
        }
    
        if (m & 1)
        {
            for (int i = 1; i <= n; i++)
            {
                LinkToEnd(ans, bruteforce(i, 1, a, n, m));
            }
        }
    
        for (int i = 1 + (n & 1); i <= n; i += 2)
        {
            for (int j = 1 + (m & 1); j <= m; j += 2)
            {
                LinkToEnd(ans, solve(i, j, a));
            }
        }
    
        int result = ans.size() / 3;
        cout << result << endl;
    
        for (int i = 0; i < result; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                cout << ans[3 * i + j].first << " " << ans[3 * i + j].second << " ";
            }
            cout << endl;
        }
    }
    
    signed main()
    {
        presolve();
    
        // for(int i=0;i<2;i++)
        // {
        //     for(int j=0;j<2;j++)
        //     {
        //         for(int k=0;k<2;k++)
        //         {
        //             for(int l=0;l<2;l++)
        //             {
        //                 auto& x=s[i][j][k][l];
        //                 for(auto p:x)
        //                 {
        //                     cout<<p.first<<","<<p.second<<"  ";
        //                 }
        //                 cout<<endl;
        //             }
        //         }
        //     }
        // }
    
        int t;
        cin >> t;
        while (t--)
        {
            solve();
        }
    }
    
  • 相关阅读:
    ssh无密码登录设置方法以及出现问题 ECDSA host key 和IP地址对应的key不同的解决
    asp.net core 3 Swagger 添加 Authorization [Bearer token]
    asp.net core3 发布到IIS
    asp.net core 3.1 使用log4net
    asp.net core 3 跨域
    解决'vue' 不是内部或外部命令,也不是可运行的程序 或批处理文件的方法
    ReSharper 安装没有提示功能
    Python3 安装MySQL驱动
    win10 安装 Python 和 pip 详解
    Win10下 80端口被system(pid=4)占用的解决方法
  • 原文地址:https://www.cnblogs.com/mollnn/p/14072885.html
Copyright © 2020-2023  润新知