loj 6030「雅礼集训 2017 Day1」矩阵

题目描述

有一个 n×n n \times nn×n 的矩阵,每个位置 (i,j) (i, j)(i,j) 如果是 . 表示为白色,如果是 # 表示为黑色。

初始时,每个位置可以是黑色或白色的,(i,j) (i, j)(i,j) 位置的值会作为 ai,j a_{i, j}ai,j 给你。

现在有一种操作,选择两个整数 i,j∈[1,n] i, j \in [1, n]i,j[1,n],记 (i,1),(i,2),…,(i,n) (i, 1), (i, 2), \ldots, (i, n)(i,1),(i,2),,(i,n) 的颜色为 C1,C2,…Cn C_1, C_2, \ldots C_nC1,C2,Cn,将 (1,j),(2,j),…,(n,j) (1, j), (2, j), \ldots, (n, j)(1,j),(2,j),,(n,j) 的颜色赋为 C1,C2,…,Cn C_1, C_2, \ldots, C_nC1,C2,,Cn

你的任务是将整个矩阵变成全黑,如果能够办到,输出最少步数,否则输出 −1 -11

      

        一道看起来没有什么算法的题,似乎就只能去推结论了。

        最先开始我们可以发现,如果有一个黑点,那么把它复制到与它相关的每一列,可以构造出来一个全黑行,这个全黑行还可以把每一列去覆盖,所以如果至少有一个黑点这题就是有解的。

        下面第一步先按列考虑,首先如果一列含有白色格点,那么这一列肯定需要被涂至少一次,所有设有白色格点的列共为tot列则至少需要被涂tot次。

        第二步再按行考虑,对于每一行来说,这一行是可以给任何一列涂的,由题意可知,那么如果有一行全黑,那么它只需要将第一步所考虑的tot列一涂,即可完成了,所以我们下面假设没有一行是全黑。

       由于用不是全黑的行来专心涂列是没有意义的,因为还会引进新的白点,所以我们可以枚举将哪一行构造为全黑,然后加上tot即可。

       假设当前在第i行,那么

       (1)如果第i列至少有一个黑色的,那么它必定可以转移到第i行的任意一个位置,所以由于一次只能去覆盖一列,所以假设本行有x个白色的块,那么则需要x次来将它们变成黑色,由于涂的是有白色的列,所以不会将全黑列增添白点,而且由于当前假设的前提是没有一行是全黑的,我们也不能通过竖着刷将一列变为全黑,所以有白色格点的仍然为tot列。

        (2)如果第i列是一个全白的列,我们并不能通过第i列的任何一个值来将第i行的空缺补成黑色,而又因为至少有一个黑点,所以肯定可以通过一次赋颜色,使第i列有一个黑店,然后与(1)同理,只多了一个步骤,所以如果第i列没有黑点,则这一行变为全黑的次数为x+1。

       综上,最终答案就是tot(有白色格点的行数)+min(hang[i](第i行白色格点的个数)+!hang[i](第i行是否全为白点))

      下附AC代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 1005
using namespace std;
int n,flag,tot;
char s[maxn][maxn];
int lie[maxn],hang[maxn];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s[i]+1);
		int flag1=0;
		for(int j=1;j<=n;j++)
		{
			if(s[i][j]=='#') 
			flag=1,hang[i]++,lie[j]=true;
			if(s[i][j]=='.')
			flag1=1;
		}
		tot+=flag1;
	}
	if(!flag){printf("-1\n");return 0;}
	int ans=123456789;
	for(int i=1;i<=n;i++)
	ans=min(ans,tot+n-hang[i]+!lie[i]);
	printf("%d\n",ans);
} 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值