Description
给一个N*N的01矩阵, 求一个面积最大的全为1的正方形子矩阵. 输出它的面积.
Input
输入文件square.in的第一行包含一个正整数N.
接下来N行, 每行N个数, 保证不是0就是1. 每行相邻两个数之间没有空格.
Output
输出文件为square.out,仅包含一个整数表示最大的全1子正方形矩阵的面积。
Sample Input
2
11
11
Sample Output
4
DataConstraint
Hint
【数据规模和约定】
80%的数据中 N<=250;
100%的数据中 N <= 1000。
分析:
枚举每个点,二分枚举这个点右下(左下)的最大正方形。加一个剪枝优化一下就很快了。
剪枝:一个点右下(左上)的最大正方形是这个点横纵坐标的最小值。如果小于当前的答案,就不必二分了。
代码:
var
f:array [0..1001,0..1001] of longint;
n,i,j,ans,t:longint;
procedure init;
var ch:char;
s:ansistring;
begin
readln(n);
for i:=1 to n do
begin
for j:=1 to n do
begin
read(ch);
if ch='1' then t:=1 else t:=0;
f[i,j]:=f[i-1,j]+f[i,j-1]-f[i-1,j-1]+t;
end;
readln;
end;
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x)
else exit(y);
end;
function max(x,y:longint):longint;
begin
if x>y then exit(x)
else exit(y);
end;
function find(x:longint):longint;
var l,r,mid,t,t1:longint;
begin
l:=1; r:=x;
while l<=r do
begin
mid:=(l+r) shr 1;
if r-l<=1 then break;
t:=f[i,j]-f[i-mid,j]-f[i,j-mid]+f[i-mid,j-mid];
if t=mid*mid then l:=mid
else r:=mid-1;
end;
t:=f[i,j]-f[i-r,j]-f[i,j-r]+f[i-r,j-r];
t1:=f[i,j]-f[i-l,j]-f[i,j-l]+f[i-l,j-l];
if t=r*r then exit(r);
if t1=l*l then exit(l)
else exit(0);
end;
begin
init;
for i:=n downto 1 do
for j:=n downto 1 do
begin
if min(i,j)<ans then continue;
ans:=max(find(min(i,j)),ans);
end;
writeln(ans*ans);
end.