bzoj 1057 悬线法

题意: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 ax) 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
bzoj 1057 悬线法_第1张图片

你可能感兴趣的:(bzoj,模板,悬线法)