zoukankan      html  css  js  c++  java
  • [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();
        }
    }
    
  • 相关阅读:
    C/C++中的内存对齐 C/C++中的内存对齐
    Java编程提高性能时需注意的地方
    微软HoloLens技术解谜
    MySQL索引原理及慢查询优化
    mysql 2006
    第9周个人总结
    第十周任务安排
    下一阶段学习安排
    写在软考弃考之后
    第九周任务安排
  • 原文地址:https://www.cnblogs.com/mollnn/p/14072885.html
Copyright © 2011-2022 走看看