• CF1592F1 Alice and Recoloring 1


    https://www.luogu.com.cn/blog/DreamNOI2022/post-ti-xie-cf1592f1-alice-and-recoloring-1-post
    超级妙妙题!

    题意:

    给定一个 \(n \times m\) 的矩阵,初始时所有格子都是白色,可以进行以下四种操作:

    1、翻转一个以 \((1,1)\) 为左上角的任意子矩阵的所有颜色,代价为 \(1\)

    2、翻转一个以 \((n,1)\) 为左下角的任意子矩阵的所有颜色,代价为 \(2\)

    3、翻转一个以 \((1,m)\) 为右上角的任意子矩阵的所有颜色,代价为 \(4\)

    4、翻转一个以 \((n,m)\) 为右下角的任意子矩阵的所有颜色,代价为 \(3\)

    求将初始局面变为给定局面花费代价的最小值。

    首先只有黑白两种颜色,所以将一个格子翻转偶数次,相当于没有翻转。

    其次,将初始局面变为给定局面,等价于将给定局面变为初始局面。因此问题可以转化成给定一个局面,要将这个局面全部变为白色格子所花费的最小代价。

    发现这四种操作好像比较对称,考虑进行一些转化。

    对于操作 \(2\),翻转一个以 \((n,1)\) 为左下角,\((x,y)\) 为右上角的矩阵,可以转化为使用两次操作 \(1\),第一次翻转以 \((1,1)\) 为左上角,\((n,y)\) 为右下角的矩形,第二次翻转以 \((1,1)\) 为左上角,\((x-1,y)\) 为右下角的矩形。

    显然这两种操作完全等价,花费的代价也相同。因此,操作 \(2\) 没有任何意义。

    类似地,对于操作 \(3\),翻转一个以 \((1,m)\) 为右上角,\((x,y)\) 为左下角的矩阵,可以转化为使用两次操作 \(1\),第一次翻转以 \((1,1)\) 为左上角,\((x,m)\) 为右下角的矩形,第二次翻转以 \((1,1)\) 为左上角,\((x,y-1)\) 为右下角的矩形。

    这两种操作也是完全等价的,但是两次操作 \(1\) 只需要花费 \(2\) 代价,因此操作 \(3\) 也没有意义。

    容易知道操作 \(4\) 无法转化为使用不超过三次的操作 \(1\),因此操作 \(4\) 是有意义的。

    于是证明了只有操作 \(1\) 和操作 \(4\) 有意义。下面考虑如何操作。

    显然矩阵修改不好维护且十分麻烦,最好将其转化为单点修改。

    可以对原矩阵 \(c\) 进行一个巧妙的转化:令白色格子为 \(0\),黑色格子为 \(1\)。设 \(a_{i,j}\) 代表 \((c_{i,j}+c_{i+1,j}+c_{i,j+1}+c_{i+1,j+1}) \bmod 2\) 的结果。

    容易知道,将原局面全部变成白色格子的充要条件为对于任意 \(1 \le i,j \le n,a_{i,j}=0\)。于是问题转化为将所有 \(a_{i,j}\) 变为 \(0\) 的最小方案。

    考虑对于操作 \(1\),翻转一个以 \((1,1)\) 为左上角,\((x,y)\) 为右下角的矩形等价于只翻转 \(a_{x,y}\)

    对于操作 \(4\),翻转一个以 \((x,y)\) 为左下角,\((n,m)\) 为右下角的矩阵,等价于只翻转 \(a_{x-1,y-1},a_{x-1,m},a_{y-1,n},a_{n,m}\)

    这两个结论可以自行画图证明,这里略去。

    这样操作 \(1\) 就是翻转一个点,代价为 \(1\),操作 \(4\) 就是翻转四个点,代价为 \(3\)

    看起来操作 \(4\) 好像更优。但是操作 \(4\) 能用必须满足两个条件:1、\(a_{x-1,y-1},a_{x-1,m},a_{y-1,n},a_{n,m}\) 均为 \(1\)(翻转 \(a_{i,j}=0\) 的点会带来负收益);2、只能进行一次(因为多次进行操作 \(4\) 会不断翻转 \(a_{n,m}\),实际上最多翻转 \(3\) 个有效点)

    所以最多进行一次操作 \(4\),剩下的点都用操作 \(1\) 完成。

    于是判断一下能否进行操作 \(4\) 并统计一下需要翻转的 \(a_{i,j}\) 的个数即可。

    时间复杂度 \(O(nm)\)

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define back return
    #define ri register int
    #define ull unsigned ll
    using namespace std;
    ll read()
    {
        ll x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        back x*f;
    }
    int n,m,ans,a[505][505],b[505][505];
    char c[505][505];
    int main()
    {
        n=read(),m=read();
        for(ri i=1;i<=n;i++)
            for(ri j=1;j<=m;j++)
            {
                cin>>c[i][j];
                if(c[i][j]=='W')
                    b[i][j]=0;
                else
                    b[i][j]=1;
            }
        for(ri i=1;i<=n;i++)
            for(ri j=1;j<=m;j++)
                a[i][j]=(b[i][j]+b[i][j+1]+b[i+1][j]+b[i+1][j+1])%2;
        for(ri i=1;i<=n;i++)
            for(ri j=1;j<=m;j++)
                if(a[i][j]==1)  
                    ans++;
        if(a[n][m])
            for(ri i=1;i<=n;i++)
                for(ri j=1;j<=m;j++)
                    if(a[i-1][j-1]&&a[i-1][m]&&a[n][j-1])   
                    {
                        cout<<ans-1<<"\n";
                        back 0;
                    }
        cout<<ans<<"\n";
        back 0;
    }
    
  • 相关阅读:
    [POJ][3072][Robot]
    [HDU][4021][24 Puzzle]
    [POJ][1228][Grandpa's Estate]
    [POJ][3662][Telephone Lines]
    [HDU][4007][Dave]
    [POJ] [1264] [SCUD Busters]
    ASP.NET中的COOKIE
    分享至...(源码)
    php获取图片并输出
    VNC 服务器/本地复制粘贴实现命令
  • 原文地址:https://www.cnblogs.com/CHK666/p/15839532.html
Copyright © 2020-2023  润新知