CF370D Broken Monitor 题解


题意

一个 \(n \times m\) 的显示器,有的点是白色的,有的点是黑色的,求一个最小的正方形方框,使所有白点都在方框上。

分析

首先确定方框的边长,这个长度就是最左最右白块横坐标的差和最上最下白块纵坐标的差的最大值。如果边长比显示器长、宽的最小值大,那么不可能找到符合要求的方框。确定边长后,我们可以枚举每一个点作为左上角,检查这个方框上的白点数是否和总白点数相等。再加上前缀和优化即可。

代码

#include 
using namespace std;
const int MAXN=2e3+7;
inline void qread(){}template
inline void qread(T1 &a,T2&... b)
{
	register T1 x=0;register bool f=false;char ch=getchar();
	while(ch<'0') f|=(ch=='-'),ch=getchar();
	while(ch>='0') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	x=(f?-x:x);a=x;qread(b...);
}
inline int qmax(const int &x,const int &y){return x>y?x:y;}
inline int qmin(const int &x,const int &y){return x=qmin(n,m)) return printf("-1\n"),0;
	for(i=1;i<=n;i++) 
	{
		for(j=1;j<=m;j++) 
		{
			col[j][i]=col[j][i-1]+(a[i][j]=='w'),row[i][j]=row[i][j-1]+(a[i][j]=='w');
			if(a[i][j]=='w') cnt++;
		}
	}
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=m;j++)
		{
			if(i+sz>n||j+sz>m) continue;
			int t=row[i][j+sz]-row[i][j-1]+row[i+sz][j+sz]-row[i+sz][j-1]+col[j][i+sz-2]-col[j][i]+col[j+sz][i+sz-2]-col[j+sz][i]; //方框上的白点数
			if(t==cnt)
			{
				for(int ii=i;ii<=i+sz;ii++) if(a[ii][j]!='w') a[ii][j]='+'; //左边
				for(int ii=i;ii<=i+sz;ii++) if(a[ii][j+sz]!='w') a[ii][j+sz]='+'; //右边
				for(int jj=j;jj<=j+sz;jj++) if(a[i][jj]!='w') a[i][jj]='+'; //上边
				for(int jj=j;jj<=j+sz;jj++) if(a[i+sz][jj]!='w') a[i+sz][jj]='+'; //下边
				for(i=1;i<=n;i++) printf("%s\n",a[i]+1);
				return 0;
			}
		}
	}
	printf("-1\n");
	return 0;
}