ZJOI2007 棋盘制作
【題目描述】
國(guó)際象棋是世界上最古老的博弈游戲之一,和中國(guó)的圍棋、象棋以及日本的將棋同享盛名。據(jù)說(shuō)國(guó)際象棋起源于易經(jīng)的思想,棋盤(pán)是一個(gè)8*8大小的黑白相間的方陣,對(duì)應(yīng)八八六十四卦,黑白對(duì)應(yīng)陰陽(yáng)。而我們的主人公小Q,正是國(guó)際象棋的狂熱愛(ài)好者。作為一個(gè)頂尖高手,他已不滿(mǎn)足于普通的棋盤(pán)與規(guī)則,于是他跟他的好朋友小W決定將棋盤(pán)擴(kuò)大以適應(yīng)他們的新規(guī)則。小Q找到了一張由N*M個(gè)正方形的格子組成的矩形紙片,每個(gè)格子被涂有黑白兩種顏色之一。小Q想在這種紙中裁減一部分作為新棋盤(pán),當(dāng)然,他希望這個(gè)棋盤(pán)盡可能的大。不過(guò)小Q還沒(méi)有決定是找一個(gè)正方形的棋盤(pán)還是一個(gè)矩形的棋盤(pán)(當(dāng)然,不管哪種,棋盤(pán)必須都黑白相間,即相鄰的格子不同色),所以他希望可以找到最大的正方形棋盤(pán)面積和最大的矩形棋盤(pán)面積,從而決定哪個(gè)更好一些。于是小Q找到了即將參加全國(guó)信息學(xué)競(jìng)賽的你,你能幫助他么?
【輸入文件】
第一行包含兩個(gè)整數(shù)N和M,分別表示矩形紙片的長(zhǎng)和寬。接下來(lái)的N行包含一個(gè)N * M的01矩陣,表示這張矩形紙片的顏色(0表示白色,1表示黑色)。
【輸出文件】
包含兩行,每行包含一個(gè)整數(shù)。第一行為可以找到的最大正方形棋盤(pán)的面積,第二行為可以找到的最大矩形棋盤(pán)的面積(注意正方形和矩形是可以相交或者包含的)。
【輸入樣例】
3 3
1 0 1
0 1 0
1 0 0
【輸出樣例】
4
6
【數(shù)據(jù)規(guī)模】
對(duì)于20%的數(shù)據(jù),N, M ≤ 80
對(duì)于40%的數(shù)據(jù),N, M ≤ 400
對(duì)于100%的數(shù)據(jù),N, M ≤ 2000
【題目分析】
首先把矩陣轉(zhuǎn)化一下,把橫縱坐標(biāo)和為偶數(shù)點(diǎn)的值取反,這樣就轉(zhuǎn)化成求最大的'0'或'1'矩陣。
我們只討論對(duì)于0的求法,對(duì)1類(lèi)似。
首先是最大正方形問(wèn)題,這是一個(gè)經(jīng)典的DP問(wèn)題,f[i,j]表示以i,j為右下角的最大正方形的邊長(zhǎng),那么a[i,j]=0時(shí),f[i,j]=min(f[i-1,j-1],f[i-1,j],f[i,j-1])+1,a[i,j]=1時(shí),f[i,j]=0,f數(shù)組中的最大值即為第一問(wèn)的答案。
對(duì)于第二問(wèn),我們用一個(gè)單調(diào)棧來(lái)解決。
首先枚舉最大矩形的下邊界,對(duì)于每一個(gè)下邊界維護(hù)兩個(gè)(也可以說(shuō)是兩次)單調(diào)棧,一次正向,一次反向,用s[i,j]表示從a[i,j]開(kāi)始向上最多能擴(kuò)展出幾個(gè)0,如果a[i,j]=1,那么s[i,j]=0,這樣維護(hù)棧中元素的s值遞增,每次元素出棧時(shí)就可以確定這個(gè)元素可以向左或向右擴(kuò)展多少長(zhǎng)度了,即找到了第一個(gè)s值小于該元素的位置,然后用每個(gè)元素的s值乘以向左向右擴(kuò)展的長(zhǎng)度和去更新第二問(wèn)的答案就可以了。
由于每個(gè)元素最多進(jìn)棧或出棧一次,每次的復(fù)雜度為O(n),這樣總的時(shí)間復(fù)雜度就是O(n^2);
【代碼實(shí)現(xiàn)】
Code 1 program lyd1057; 2 var a:array[0..2000,0..2000]of 0..1; 3 f:array[0..2000,0..2000]of longint; 4 s:array[0..2000,0..2000]of longint; 5 z:array[0..2000]of longint; 6 l,r,p:array[0..2000]of longint; 7 ans1,ans2,i,j,m,n,k,t:longint; 8 function max(a,b:longint):longint; 9 begin 10 if a>b then exit(a) 11 else exit(b); 12 end; 13 function min(a,b:longint):longint; 14 begin 15 if a<b then exit(a) 16 else exit(b); 17 end; 18 procedure dp(o:longint); 19 var i,j:longint; 20 begin 21 for i:=1 to n do 22 if a[1,i]=o then s[1,i]:=1; 23 for i:=2 to m do 24 for j:=1 to n do 25 if a[i,j]=o then s[i,j]:=s[i-1,j]+1 26 else s[i,j]:=0; 27 for i:=1 to m do 28 for j:=1 to n do 29 begin 30 if a[i,j]=o then f[i,j]:=min(f[i-1,j-1],min(f[i-1,j],f[i,j-1]))+1 31 else f[i,j]:=0; 32 ans1:=max(ans1,f[i,j]); 33 end; 34 for i:=1 to m do 35 begin 36 fillchar(l,sizeof(l),0); 37 fillchar(r,sizeof(r),0); 38 t:=0; 39 for j:=1 to n do 40 begin 41 while (t>0)and(s[i,j]<s[i,z[t]]) do 42 begin 43 r[z[t]]:=j-z[t]; 44 dec(t); 45 end; 46 if a[i,j]=o then 47 begin 48 inc(t); 49 z[t]:=j; 50 end; 51 end; 52 for j:=t downto 1 do 53 r[z[j]]:=n-z[j]+1; 54 t:=0; 55 for j:=n downto 1 do 56 begin 57 while (t>0)and(s[i,j]<s[i,z[t]]) do 58 begin 59 l[z[t]]:=z[t]-j; 60 dec(t); 61 end; 62 if a[i,j]=o then 63 begin 64 inc(t); 65 z[t]:=j; 66 end; 67 end; 68 for j:=t downto 1 do 69 l[z[j]]:=z[j]; 70 for j:=1 to n do 71 if a[i,j]=o then 72 begin 73 p[j]:=l[j]+r[j]-1; 74 ans2:=max(ans2,p[j]*s[i,j]); 75 end; 76 end; 77 end; 78 begin 79 readln(m,n); 80 for i:=1 to m do 81 for j:=1 to n do 82 begin 83 read(a[i,j]); 84 if (i+j)and 1=0 then a[i,j]:=1-a[i,j]; 85 end; 86 dp(0); 87 dp(1); 88 ans1:=sqr(ans1); 89 writeln(ans1); 90 writeln(ans2); 91 end.?
轉(zhuǎn)載于:https://www.cnblogs.com/whitecloth/archive/2012/04/11/2443003.html
總結(jié)
以上是生活随笔為你收集整理的ZJOI2007 棋盘制作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows Phone 7 实战第二
- 下一篇: 如何投影一个纹理