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();
        }
    }
    
  • 相关阅读:
    街边的泥人张
    没事试试50mm1.4
    WWOOF介绍一下,但貌似我们利用不了
    护照和签证
    071205还是晴photo
    忘年旅行
    12月6日大雪
    12月5日
    周六
    071204 晴
  • 原文地址:https://www.cnblogs.com/mollnn/p/14072885.html
Copyright © 2011-2022 走看看