題面:
輸入第一行包含一個整數 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, nm 的總和不超過 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;
}