Link.
Codeforces F1
Codeforces F2
Luogu F1
Luogu F2
Description.
有一个 01 矩阵,现在你有以下四种操作
- 选择一个包括 \((1,1)\) 的矩阵并对其反色
- 选择一个包括 \((n,1)\) 的矩阵并对其反色
- 选择一个包括 \((1,m)\) 的矩阵并对其反色
- 选择一个包括 \((n,m)\) 的矩阵并对其反色
每个操作的权值是给定的,其中
1 代价 | 2 代价 | 3 代价 | 4 代价 | |
---|---|---|---|---|
F1 | 1 | 2 | 4 | 3 |
F2 | 1 | 3 | 4 | 2 |
问全都消成 \(0\) 的最小代价。
Solution.
首先,发现不管是 F1 还是 F2 2
和 3
操作根本没用。
因为 2
和 3
总是可以通过 \(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;
}