题意:
给一个n行m列的只由01组成的矩阵,每次选择一个L形的区域。方向不限,必须包含至少一个1,将此区域内全部置为0,问将整个区域置为0最多需要多少次操作。
思路:
如果整个矩阵没0,则答案是1的个数(下称为num)-2;
若存在连续的0(只相邻的8个单位格内任意一个还有0),则为num;
若只存在蛋单个零散0,则为num-1;
证明很简单,自己去试一下就知道,如果存在连续0,则一定可以一个一个的消掉1。后续结论都是基于此推出来的。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int inf=1e9+9;
const ll INF=1e18l;
/*
priority_queue<int> big_heep;
priority_queue<int,vector<int>,greater<int> > small_heep;
struct cmp{//if return true,it means that the number in the left was smaller than the right one
bool operator () (int a,int b){
}
};
*/
int a[1005][1005];
void work(){
int n,m;
cin>>n>>m;
int num=0;
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
char c;
cin>>c;
if (c=='0') a[i][j]=0;
if (c=='1') a[i][j]=1;
if (a[i][j]==1) num++;
}
}
bool check=true;
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
if (a[i][j]==0){
check=false;
if (((i-1>=1) and a[i-1][j]==0) or ((i+1<=n) and a[i+1][j]==0) or
((j+1<=m) and a[i][j+1]==0) or ((j-1>=1) and a[i][j-1]==0) or
((i+1<=n) and (j+1<=m) and a[i+1][j+1]==0) or (i-1>=1 and j-1>=1 and a[i-1][j-1]==0)
or (i-1>=1 and j+1<=m and a[i-1][j+1]==0) or (i+1<=n and j-1>=1 and a[i+1][j-1]==0)){
cout<<num<<"\n";
return;
}
}
}
}
if (check) cout<<num-2<<"\n";
else cout<<num-1<<"\n";
return;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll t;
cin>>t;
while (t--){
work();
}
return 0;
}