正题
题目链接:https://www.luogu.com.cn/problem/CF525D
题目大意
n∗mn*mn∗m的网格,有∗*∗和...,每次可以将∗*∗改成...。求最少操作使得每个...所在的联通块都是一个矩形。
解题思路
因为一个大矩形中每一个小块也是一个矩形,反之同理。那么我们只需要统计每个2∗22*22∗2的网格如果只有一个∗*∗那么这个∗*∗是需要去除的,然后用类似bfsbfsbfs的方法来扩展即可。
时间复杂度O(nm)O(nm)O(nm)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=2100;
int n,m,v[N][N],a[N][N];
queue<int> qx,qy;
char s[N];
void Change(int x,int y){v[x-1][y-1]--;v[x][y]--;v[x-1][y]--;v[x][y-1]--;if(v[x-1][y-1]==1)qx.push(x-1),qy.push(y-1);if(v[x-1][y]==1)qx.push(x-1),qy.push(y);if(v[x][y-1]==1)qx.push(x),qy.push(y-1);if(v[x][y]==1)qx.push(x),qy.push(y);a[x][y]=0;return;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",s+1);for(int j=1;j<=m;j++)a[i][j]=(s[j]=='*');}for(int i=1;i<n;i++)for(int j=1;j<m;j++){v[i][j]=a[i][j]+a[i+1][j]+a[i][j+1]+a[i+1][j+1];if(v[i][j]==1)qx.push(i),qy.push(j);}while(!qx.empty()){int x=qx.front(),y=qy.front();qx.pop();qy.pop();if(a[x][y])Change(x,y);if(a[x+1][y])Change(x+1,y);if(a[x][y+1])Change(x,y+1);if(a[x+1][y+1])Change(x+1,y+1);}for(int i=1;i<=n;i++,putchar('\n'))for(int j=1;j<=m;j++)if(a[i][j])printf("*");else printf(".");return 0;
}