這道題,題的意思就是去找需要刷的數目最小並且能使得這點所對應的行和列均爲*;
通過理解,不難發現:最小不就是行對應枚舉列是行和列和(我這裏是 . 的個數的和)最小嗎?(有了這個想法之後就好辦了);所以我可以用兩個一維數組存下每行對應的個數,沒列對應的個數;
然後枚舉矩陣裏面的每個點就可以算出來最小值了;注意這裏需要一點思維:就是我需要先把枚舉到的點給-去,也就是n+m-2因爲中間不能重疊(如果學過容斥定理或者集合的就應該很好理解);
如果這點對於的是 . 那麼我就需要刷一個,如果不是 . 那麼我就不需要算他,因爲行和列統計的是*的個數:
所以AC代碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define M 50050
int main(){
ll T,n,m,r[M],c[M],Min;
string s[M];
scanf("%lld",&T);
while(T--){
Min=0x3f3f3f3f;
memset(r,0,sizeof(r));
memset(c,0,sizeof(c));
scanf("%lld %lld",&n,&m);
for(int i=0;i<n;i++){
cin>>s[i];
for(int j=0;j<m;j++){
if(s[i][j]=='*')r[i]++;
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(s[j][i]=='*')c[i]++;
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(s[i][j]=='.'){//就是這裏需要討論一下,用筆畫一下就可以理解,因爲我這裏前面是存的*的個數
Min=min(Min,n+m-2-(r[i]+c[j])+1);
}else Min=min(Min,n+m-(r[i]+c[j])+(s[i][j]=='.'));
}
}
printf("%lld\n",Min);
}
return 0;
}