题目描述
国际象棋是世界上最古老的博弈游戏之一,和中国的围棋、象棋以及日本的将棋同享盛名。据说国际象棋起源于易经的思想,棋盘是一个8×8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳。
而我们的主人公小Q
,正是国际象棋的狂热爱好者。作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W
决定将棋盘扩大以适应他们的新规则。
小Q
找到了一张由N×M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一。小Q
想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。
不过小Q
还没有决定是找一个正方形的棋盘还是一个矩形的棋盘(当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色),所以他希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。
于是小Q
找到了即将参加全国信息学竞赛的你,你能帮助他么?
其实这就是个悬线法,就像我们人工找最大矩阵一样,先找一块空的地方
(红色为不能到达的地方)
粉色是随便找的一个点(为什么用粉色?粉色可爱嘛。)
先向右走,只能到达最右的点,同理左边只能到达左边的点
至于上下,因为我们是先从左向右扫,扫完第一行才扫第二行,因此第二行的长度可以从第一行上转移过来,就有up[i][j]= up[i-1][j]+1;最终求面积只要。
矩形:(rght[i][j]-lft[i][j]+1)*up[i][j] //记得加一,左边那一个不能忘掉。
正方形:只要在min(rght[i][j]-lft[i][j]+1,up[i][j])之间去最小值再平方就行了。
总的时间复杂度(NM),空间复杂度(NM),
如果任想继续深入,可以阅读这篇文章。https://blog.csdn.net/clover_hxy/article/details/50532289?locationNum=1&fps=1
(膜拜大神~~~~~~~~~~~~~~~~~~~~~~~~)
最后附上鄙人弱弱的代码
a[i][j]储存图的信息
up[i][j]代表第i,j点所能到达最大高度 up[i][j]= up[i-1][j]+1
rght[i][j]代表第i,j点所能到达最右的地方 rght[i][j]=min(rght[i][j],rght[i-1][j])
lft[i][j]代表第i,j点所能到达最左的地方 lft[i][j]= max(lft[i][j],lft[i-1][j])
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define re register int
using namespace std;
const int maxn = 2005;
int a[maxn][maxn],n,m,up[maxn][maxn],lft[maxn][maxn],rght[maxn][maxn],ans1,ans2;
inline int read(){
int x=0,f=1;
char ch = getchar();
while(ch<'0'||ch>'9'){if(ch == '-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int main(){
ios::sync_with_stdio(false);
n=read(); m=read();
for(re i=1; i<=n; i++){
for(re j=1; j<=m; j++){
a[i][j] = read();
lft[i][j] = rght[i][j] = j;
up[i][j] = 1;
}
}
for(re i=1;i<=n; i++){
for(re j=2; j<=m; j++){
if(a[i][j]+a[i][j-1]==1)
lft[i][j] = lft[i][j-1];
}
}
for(re i=1; i<=n; i++){
for(re j=m-1; j; j--){
if(a[i][j]+a[i][j+1] == 1){
rght[i][j] = rght[i][j+1];
}
}
}
for(re i=1; i<=n; i++){
for(re j=1; j<=m; j++){
if(i>1&& a[i][j]+a[i-1][j]==1){
lft[i][j] = max(lft[i][j],lft[i-1][j]);
rght[i][j] = min(rght[i][j],rght[i-1][j]);
up[i][j] = up[i-1][j]+1;
}
re dist1 = rght[i][j]-lft[i][j]+1;
re dist2 = min(dist1,up[i][j]);
ans1 = max(ans1,dist2*dist2);
ans2 = max(ans2,dist1*up[i][j]);
}
}
cout << ans1 << endl << ans2 << endl;
return 0;
}