【题目描述】
国际象棋是世界上最古老的博弈游戏之一,和中国的围棋、象棋以及日本的将棋同享盛名。据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳。
而我们的主人公小Q,正是国际象棋的狂热爱好者。作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则。
小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一。小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。
不过小Q还没有决定是找一个正方形的棋盘还是一个矩形的棋盘(当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色),所以他希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。
于是小Q找到了即将参加全国信息学竞赛的你,你能帮助他么?
【数据范围】
对于20%的数据,N, M ≤ 80
对于40%的数据,N, M ≤ 400
对于100%的数据,N, M ≤ 2000
【题解】
这道题是浙江省07年的省选题,前几天做过一道类似的题目,所以顺手就刷了一下。这里介绍国家集训队03年的《浅谈用极大化思想解决最大子矩形问题》中提到的一种方法。
我们先考虑最大的矩形面积。很容易得到,最大的矩形一定是一个极大矩形(即四边都不能向上拓展的矩阵),也就是说,他的上边要么是整个矩阵的上边,要么被一对相同的数卡住。利用这个性质,我们可以得到一个优秀的算法:设行指针i,列指针j,j从左往右,i从上往下扫描,计算出当前点(j,i)与其上方能拓展的最远点所夹的最大矩形面积。由于刚才提到的性质,这样的扫描一定能扫过最大矩形的上下边界,而左右边界则可以用一个O(n^2)的动规来解决。这样,我们就可以在O(n^2)的时间内求出最大矩形。
而解决了求最大矩形的问题后,最大正方形的问题也就好解决了。套用最大矩形的算法,可以轻松的求出最大正方形,具体实现请参看我的程序。
Code
program chess;
type
int=longint;
var
i,j,m,n:int;
matrix,max_l,max_r:array[0..2001,0..2001]of int;
function min(x,y:int):int;
begin
if x<y then exit(x)
else exit(y);
end;
procedure prepare;
begin
for i:=1 to n do
for j:=2 to m do
if(matrix[i,j]<>matrix[i,j-1])then
max_l[i,j]:=max_l[i,j-1]+1
else max_l[i,j]:=0;
for i:=1 to n do
for j:=m-1 downto 1 do
if(matrix[i,j]<>matrix[i,j+1])then
max_r[i,j]:=max_r[i,j+1]+1
else max_r[i,j]:=0;
for i:=1 to m do matrix[0,i]:=matrix[1,i];
end;
procedure get_ans;
var min_l,min_r,s,l,ans2,ans:int;
begin
ans:=0;ans2:=0;
for j:=1 to m do begin
for i:=1 to n do begin
if matrix[i,j]=matrix[i-1,j]then begin
min_l:=maxlongint;min_r:=maxlongint;l:=0;
end;
min_l:=min(min_l,max_l[i,j]);
min_r:=min(min_r,max_r[i,j]);
s:=min_l+min_r+1;inc(l);
if ans<l*s then ans:=l*s;
if ans2<min(l,s)then ans2:=min(l,s);
end;
end;
writeln(ans2*ans2);
write(ans);
end;
begin
assign(input,'data.txt');reset(input);
read(n,m);
for i:=1 to n do
for j:=1 to m do read(matrix[i,j]);
prepare;
get_ans;
end.
BY QW
转载请注明出处