• CF1592F Alice and Recoloring 题解


    Codeforces F1
    Codeforces F2
    Luogu F1
    Luogu F2

    Description.

    有一个 01 矩阵,现在你有以下四种操作

    1. 选择一个包括 \((1,1)\) 的矩阵并对其反色
    2. 选择一个包括 \((n,1)\) 的矩阵并对其反色
    3. 选择一个包括 \((1,m)\) 的矩阵并对其反色
    4. 选择一个包括 \((n,m)\) 的矩阵并对其反色

    每个操作的权值是给定的,其中

    1 代价 2 代价 3 代价 4 代价
    F1 1 2 4 3
    F2 1 3 4 2

    问全都消成 \(0\) 的最小代价。

    Solution.

    首先,发现不管是 F1 还是 F2 23 操作根本没用。
    因为 23 总是可以通过 \(2\)1 操作来完成。
    肯定先贪心用 \(1\) 操作来覆盖。
    这里相当于做个二阶差分。
    考虑用 \(3\) 操作来替换 \(1\) 操作。
    F1 的话就考虑如果有 \((n,m),(a,b),(a,m),(b,n)\) 就可以替换成 \(1\)\((a,b)_3\)
    可以使答案减小当且仅当 \((n,m),(a,b),(a,m),(b,n)\) 都是 \(1\)
    所以只需要替换一次。
    F2 的话同理,\((n,m)\ne 1\) 时也可以替换使答案减小。
    所以需要对其他都进行二分图匹配,先替换掉最多的 \(1\)
    然后再判断 \((n,m)\) 即可。

    Coding.

    点击查看 F1 代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    int n,m;char ch[505][505],fg[505][505];
    int main()
    {
    	read(n,m);for(int i=1;i<=n;i++) scanf("%s",ch[i]+1);
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ch[i][j]=ch[i][j]=='B';
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) fg[i][j]=ch[i][j]^ch[i][j+1]^ch[i+1][j]^ch[i+1][j+1];
    	int rs=0;for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) rs+=fg[i][j];
    	if(fg[n][m]) for(int i=1;i<n;i++) for(int j=1;j<m;j++)
    		if(fg[i][j]&&fg[i][m]&&fg[n][j]) return printf("%d\n",rs-1),0;
    	return printf("%d\n",rs),0;
    }
    
    点击查看 F2 代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    int n,m,mt[505];char ch[505][505],fg[505][505],vs[505];
    inline char dfs(int x)
    {
    	for(int y=1;y<m;y++) if(fg[x][y]&&fg[x][m]&&fg[n][y]&&!vs[y])
    		{vs[y]=1;if(!mt[y]||dfs(mt[y])) return mt[y]=x,1;}
    	return 0;
    }
    int main()
    {
    	read(n,m);for(int i=1;i<=n;i++) scanf("%s",ch[i]+1);
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ch[i][j]=ch[i][j]=='B';
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) fg[i][j]=ch[i][j]^ch[i][j+1]^ch[i+1][j]^ch[i+1][j+1];
    	int rs=0;for(int i=1;i<n;i++) memset(vs,0,sizeof(vs)),dfs(i);
    	for(int j=1,i;j<m;j++) if(mt[j]) i=mt[j],fg[i][j]^=1,fg[i][m]^=1,fg[n][j]^=1,fg[n][m]^=1,rs+=2;
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) rs+=fg[i][j];
    	int sm=rs-1;if(fg[n][m]) for(int i=1;i<n;i++) for(int j=1;j<m;j++)
    		{int vl=sm-fg[i][j]-fg[i][m]-fg[n][j],tp=3-fg[i][j]-fg[i][m]-fg[n][j];rs=min(rs,tp+vl+2);}
    	return printf("%d\n",rs),0;
    }
    
  • 相关阅读:
    游戏开发热门技术浅析
    SpringMVC文件分片上传,断点续传
    浏览器文件分片上传,断点续传
    网页文件分片上传,断点续传
    Web文件分片上传,断点续传
    JavaScript文件分片上传,断点续传
    js文件分片上传,断点续传
    html5文件分片上传,断点续传
    vue文件分片上传,断点续传
    csharp文件分片上传,断点续传
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15367878.html
Copyright © 2020-2023  润新知