B-Q老师与十字叉

B-Q老师与十字叉

一、题目描述

Q老师 得到一张 n 行 m 列的网格图,上面每一个格子要么是白色的要么是黑色的。

Q老师认为失去了 十字叉 的网格图莫得灵魂. 一个十字叉可以用一个数对 x 和 y 来表示, 
其中 1 ≤ x ≤ n 并且 1 ≤ y ≤ m, 满足在第 x 行中的所有格子以及在第 y 列的 所有格子都是黑色的

在这里插入图片描述

Q老师 得到了一桶黑颜料,他想为这个网格图注入灵魂。
 Q老师 每分钟可以选择一个白色的格子并且把它涂黑。现在他想知道要完成这个工作,最少需要几分钟?

Input

第一行包含一个整数 q (1 ≤ q ≤ 5 * 10^4) — 表示测试组数
对于每组数据:

第一行有两个整数 n 和 m (1 ≤ n, m ≤ 5 * 10^4, n * m ≤ 4 * 10^5) — 表示网格图的行数和列数

接下来的 n 行中每一行包含 m 个字符 — '.' 表示这个格子是白色的, '*' 表示这个格子是黑色的

保证 q 组数据中 n 的总和不超过 5 * 10^4, n*m 的总和不超过 4 * 10^5

Output

答案输出 q 行, 第 i 行包含一个整数 — 表示第 i 组数据的答案

Example
Input

9
5 5
..*..
..*..
*****
..*..
..*..
3 4
****
.*..
.*..
4 3
***
*..
*..
*..
5 5
*****
*.*.*
*****
..*.*
..***
1 4
****
5 5
.....
..*..
.***.
..*..
.....
5 3
...
.*.
.*.
***
.*.
3 3
.*.
*.*
.*.
4 4
*.**
....
*.**
*.**

Output

0
0
0
0
0
4
1
1
2

二、思路与算法

本题不需要用到高级的算法,只需要读懂题意,十字叉不需要整幅图中所有黑色格子都在十字叉中,只需要图中存在十字叉即可。
所以我们只需要找出最适合成为十字叉的交叉处的格子即可。
那么我们两次遍历棋盘,一次记录每一行的白格子数目,一次记录每一列的白格子数目。
之后第三次遍历整个棋盘,对每个格子都计算如果这个格子作为十字叉的交叉处,需要涂黑几个格子,记录最少的数目。
遍历完成后,这个最少数目就是答案。

三、代码实现

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;

int q=0;   //测试组数
int n=0,m=0;   //行列数 
vector<string> board;   //棋盘
int row[50010]={0};
int col[50010]={0};

int main(){
	cin>>q;
	for(int i=0;i<q;i++){
		cin>>n>>m;
		string tmp;
		board.clear();
		for(int j=0;j<n;j++){
			tmp.clear();	cin>>tmp;
			board.push_back(tmp);
		}   //输入结束 
		for(int j=0;j<n;j++){
			row[j]=0;
			for(int k=0;k<m;k++){
				if(board[j][k]=='.'){row[j]++;	}
			}
		}   //计算每行白格子数目 
		
		for(int j=0;j<m;j++){
			col[j]=0;
			for(int k=0;k<n;k++){
				if(board[k][j]=='.'){col[j]++;	}
			}
		}   //计算每列白格子数目
		
		int ans=50010;
		for(int j=0;j<n;j++){
			for(int k=0;k<m;k++){
				if(board[j][k]=='*'){
					ans=min(ans,row[j]+col[k]);
				}
				else{
					ans=min(ans,row[j]+col[k]-1);
				}
			}
		}   //寻找answer
		cout<<ans<<"\n";
	} 
	return 0;
}

四、经验与总结

  1. 理解题意很重要,一开始不理解什么图有十字叉,什么图没有十字叉。经过观察后发现,不需要整个图中所有黑色格子都属于十字叉,而是存在一个十字叉就可以。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值