题解 CF1391D 【505】

题解 - C F 1391 D \mathrm{CF1391D}

题目意思

就是给你个 n × m n\times m 的矩阵,为了使其的任意长度为偶数的正方形子矩阵里要含有奇数个 1 1 最少要改变几个 a i , j a_{i,j} 的状态。

S o l \mathrm{Sol}

首先可以知道 4 × 4 4\times 4 的合法矩阵是不存在的,那么 min ( n , m ) > 3 \min(n,m)>3 的矩阵也是不存在的。

那么我们只要分类讨论分别 min ( n , m ) = 1 , 2 , 3 \min(n,m)={1,2,3} 的情况即可。

我们在这边钦定 n m , n 3 n\leq m,n\leq 3

对于 n = 1 n=1 的情况由于不存在偶数长度的子矩阵直接输出 0 0

对于 n = 2 , 3 n=2,3 的情况我们考虑dp。设 f i , j , k , p f_{i,j,k,p} 表示到第 i i a 3 , i = j , a 2 , i = k , a 1 , i = p a_{3,i}=j,a_{2,i}=k,a_{1,i}=p 的最少需要改变的个数。

那么就是很显然的转移,只有当每个 2 × 2 2\times 2 的小矩阵的 1 1 的个数为奇数转移,具体地就是刷表法吧。

时间复杂度 O ( max ( n , m ) × 2 2 × min ( n , m ) ) O(\max(n,m)\times2^{2\times\min(n,m)})

C o d e \mathrm{Code}

const int mod=1e9+7;
const int mo=998244353;
const int N=1e6+5;

int n,m,f[N][2][2][2],a[4][N];
char str[N];

int main()
{
	io.read(n),io.read(m);
	if(min(n,m)>3)GG;
	if(n<m)
	{
		For(i,1,n)
		{
			scanf("%s",str+1);
			For(j,1,m) a[i][j]=str[j]^48;
		}
	}
	else 
	{
		For(i,1,n) 
		{
			scanf("%s",str+1);
			For(j,1,m) a[j][i]=str[j]^48;
		}
		swap(n,m);
	}
	if(n==1) return printf("0\n"),0;
	if(n==2)
	{
		For(i,0,1) For(j,0,1) f[1][i][j][0]=(i!=a[2][1])+(j!=a[1][1]);
		For(i,2,m) For(j,0,1) For(k,0,1) f[i][j][k][0]=1e9;
		For(i,2,m) For(j,0,1) For(k,0,1) 
		For(l,0,1) For(p,0,1) if((k+j+l+p)&1)
		{
			int s=2-((j==a[2][i])+(k==a[1][i]));
			f[i][j][k][0]=min(f[i][j][k][0],f[i-1][l][p][0]+s);
		}
		int ans=1e9;
		For(i,0,1) For(j,0,1) ans=min(ans,f[m][i][j][0]);
		io.write(ans);
		return 0;
	}
	For(i,0,1) For(j,0,1) For(k,0,1) 
	{
		f[1][i][j][k]=3-((a[3][1]==i)+(a[2][1]==j)+(a[1][1]==k));
		For(l,2,m) f[l][i][j][k]=1e9;
	}
	For(l,2,m) For(i,0,1) For(j,0,1) For(k,0,1) 
	For(ii,0,1) For(jj,0,1) For(kk,0,1) if(((kk+k+jj+j)&1)&&((jj+j+i+ii)&1))
	{
		int s=3-((a[3][l]==i)+(a[2][l]==j)+(a[1][l]==k));
		f[l][i][j][k]=min(f[l-1][ii][jj][kk]+s,f[l][i][j][k]);
	}
	int ans=1e9;
	For(i,0,1) For(j,0,1) For(k,0,1) ans=min(ans,f[m][i][j][k]);
	io.write(ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/wangyiyang2/article/details/107906269