题意:n*m的棋盘,求出满足像国际象棋棋盘那样黑白相间的最大子矩阵和最大正方形
经典悬线法
一开始直接按01的情况上的裸悬线法,经亲测,所得最大正方形的答案是正确的,但是最大子矩阵的答案偏小
然后网上的大神教我做人...orz
把奇行偶列和偶行奇列位置的取反,就能把它转化为普通的求全1或全0的一般悬线法,
分别以0为障碍点和以1位障碍点跑一遍,取max
var
n,m :longint;
ans1,ans2 :longint;
map :array[0..2010,0..2010] of longint;
i,j :longint;
l,r,h :array[0..2010,0..2010] of longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
function max(a,b:longint):longint;
begin
if a<b then exit(b) else exit(a);
end;
procedure work(x:longint);
var
i,j:longint;
tt:longint;
begin
fillchar(h,sizeof(h),0);
fillchar(l,sizeof(l),0);
fillchar(r,sizeof(r),0);
//
for i:=1 to n do
begin
for j:=1 to m do
if (map[i,j]<>x) then l[i,j]:=0 else l[i,j]:=l[i,j-1]+1;
for j:=m downto 1 do
if (map[i,j]<>x) then r[i,j]:=0 else r[i,j]:=r[i,j+1]+1;
end;
//
for i:=2 to n do
for j:=1 to m do
if (map[i,j]=x) and (map[i-1,j]=x) then
begin
h[i,j]:=h[i-1,j]+1;
l[i,j]:=min(l[i,j],l[i-1,j]);
r[i,j]:=min(r[i,j],r[i-1,j]);
end;
//
for i:=1 to n do
for j:=1 to m do
ans1:=max(ans1,(h[i,j]+1)*(l[i,j]+r[i,j]-1));
for i:=1 to n do
for j:=1 to m do
begin
tt:=min(h[i,j]+1,l[i,j]+r[i,j]-1);
ans2:=max(ans2,tt*tt);
end;
end;
begin
read(n,m);
for i:=1 to n do
for j:=1 to m do read(map[i,j]);
for i:=1 to n do
for j:=1 to m do
if ((i+j) and 1=1) then map[i,j]:=map[i,j] xor 1;
work(0);
work(1);
writeln(ans2);
writeln(ans1);
end.
——by Eirlys