雅礼集训2017day1 矩阵

雅礼集训2017day1 矩阵

题目大意

给你一个 n × n n\times n n×n 01 01 01矩阵,每次操作将一行转置后赋值到一列。如果能让矩阵全为 1 1 1,则输出最小操作次数;否则输出 − 1 -1 1

1 ≤ n ≤ 1000 1\leq n\leq 1000 1n1000


题解

首先,因为在最后一次操作后矩阵全为 1 1 1,那也就是说总要让一行全为 1 1 1。在让一行全为 1 1 1后,将那些存在 0 0 0的列都赋值一下即可让矩阵全为 1 1 1

如果已经有一行全为 1 1 1,则直接赋值即可。如果没有,则枚举要使之全为 1 1 1的行。对于第 t t t行,若要让这行全为 1 1 1,需要第 t t t列存在一个为 1 1 1的位置,然后赋值给第 t t t行为 0 0 0的位置即可。如果第 t t t列不存在为 1 1 1的位置,则只要整个矩阵存在为 1 1 1的位置,都可赋值到第 t t t列。最后,对每行的结果取最小值即为答案。

当然,如果整个矩阵都为 0 0 0,答案为 − 1 -1 1

时间复杂度为 O ( n 2 ) O(n^2) O(n2)

code

#include
using namespace std;
int n,fl=0,now,ans,v1[1005],v2[1005];
char ch,a[1005][1005];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			ch=getchar();
			while(ch!='#'&&ch!='.') ch=getchar();
			a[i][j]=ch;
			if(a[i][j]=='#') fl=1;
		}
	}
	if(!fl){
		printf("-1");
		return 0;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(a[i][j]=='#'){
				++v1[i];++v2[j];
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(v1[i]==n){
			ans=0;
			for(int j=1;j<=n;j++){
				if(v2[j]<n) ++ans;
			}
			printf("%d",ans);
			return 0;
		}
	}
	ans=1e9;
	for(int t=1;t<=n;t++){
		now=0;
		if(!v2[t]) now=1;
		for(int j=1;j<=n;j++){
			if(a[t][j]=='.') ++now;
			if(v2[j]<n) ++now;
		}
		ans=min(ans,now);
	}
	printf("%d",ans);
	return 0;
}

你可能感兴趣的:(题解,题解)