传送门:洛谷-棋盘制作
题意
小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一。小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。
不过小Q还没有决定是找一个正方形的棋盘还是一个矩形的棋盘(当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色),所以他希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。
数据范围
对于100%的数据,N, M ≤ 2000
题解
本蒟蒻看到这道题,就去学了一发悬线法(欸好像例题就是这道题)
悬线指的就是图中每条上端点是障碍物/矩形上边界的竖线。
可以肯定有一个最大正方形是包含在最大矩形里的,变成为矩形较短的一边。然后我们用悬线法找出最大矩形就好了。
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,a,b;
int f[2005][2005];
int L[2005],R[2005],H[2005];
inline void fin(int x)
{
for(int i=1;i<=m;i++){
L[i]=1;R[i]=m;H[i]=0;
}
for(int i=1;i<=n;i++){
int l=0,r=m+1;
for(int j=1;j<=m;j++){
if(f[i][j]!=x){
L[j]=1;
l=j;
H[j]=0;
}else{
H[j]++;
L[j]=max(l+1,L[j]);
}
}
for(int j=m;j>=1;j--){
if(f[i][j]!=x){
R[j]=m;
r=j;
}else{
R[j]=min(r-1,R[j]);
}
int now=min(H[j],(R[j]-L[j]+1));
a=max(a,now*now);
b=max(b,H[j]*(R[j]-L[j]+1));
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&f[i][j]);
if((i+j)%2) f[i][j]=!f[i][j];
}
fin(0);fin(1);
printf("%d\n%d\n",a,b);
return 0;
}