【題目描述】
國際象棋是世界上最古老的博弈遊戲之一,和中國的圍棋、象棋以及日本的將棋同享盛名。據說國際象棋起源於易經的思想,棋盤是一個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
轉載請註明出處