小模拟:Q老师与十字叉

题面:

在这里插入图片描述输入第一行包含一个整数 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

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

sample input:

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

sample output:
0
0
0
0
0
4
1
1
2

思路:

  • 因为只需要实现一个十字架即可,所以只需要进行整个数组的遍历然后进行最小值寻找即可
  • 需要注意他的数据范围,看二位数组来记录肯定会爆掉。我是用两个一维数组分别来描述行和列,刚开始TLE是因为const int 了一个三个数组都不会爆掉的最大范围,用来定义三个数组,结果超时了。对三个数组分别定义最大值就能AC
  • 遍历所有点,计算以它为中心产生的十字架需要补多少,如果它本身是白的话,需要 -1,因为被计算了两次,最后输出最小值
  • 想要复杂度更低的话,应该寻找行列中的空白最小值然后看两个相交后需要补充的位置数,但由于他们不一定相交的位置恰好是空白点,并且最大行列不一定只有一个,记录方法上需要细想
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
//const int N=4e5+1;
int a[50001];
int b[50001];
char mul[400001];
const int INF=1e9;
int main()
{
 int q,n,m;
 scanf("%d",&q);
 while(q--)
 {
  scanf("%d %d",&n,&m);
  int count=0;
  memset(a,0,sizeof(a));
  memset(b,0,sizeof(b));
  for(int i=0;i<n;i++)
  {
   for(int j=0;j<m;j++)
   {
    cin>>mul[count];
    if(mul[count]=='.')
     a[i]++,b[j]++;
    count++;
   }
  }
  int ans=INF;
  for(int i=0;i<n;i++)
  {
   for(int j=0;j<m;j++)
   {
    int temp=a[i]+b[j];
    if(mul[i*m+j]=='.')
    temp--;
    if(temp==0)//如果为0说明找到不需要再填 
    {
     ans=0;
     break;
     } 
    ans=min(ans,temp);
   }
  }
  cout<<ans<<endl;
 }
 return 0;
 } 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章