zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    shell 冒泡算法 解决数组排序问题
    react(二)
    react(一)
    mybatis-plus:3
    lambda
    配置中心(nacos)-控制台使用
    nacos作为配置中心的简单项目配置
    nacos作为注册中心的简单项目配置
    Vue初步学习
    nacos单例模式简单搭建
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15367878.html
Copyright © 2011-2022 走看看