請你在乙個黑白矩陣中選出乙個長方形(含正方形)和正方形的子矩陣,使得所有相鄰的點顏色不一樣。
矩陣大小:兩條邊都<
=2000
<=2000
<=2
000輸入
3 31 0 1
0 1 0
1 0 0輸出4
6解釋給定矩陣:
正方形:
長方形:
我的控制台是萌萌噠#ffc0cb粉色
乙個小技巧:如果您的控制台是像我的這樣能選擇的,那麼只要按著alt就可以只選出矩形部分了。
效果圖:
懸線dp。我們用l[i
][j]
,r[i
][j]
l[i][j],r[i][j]
l[i][j
],r[
i][j
]分別表示向左,右最遠珂以延伸(延伸的條件就是黑白相間)到同一行第幾個點。u[i
][j]
u[i][j]
u[i][j
]表示向上延伸(延伸條件同上)的最大長度。(這是懸線dp的套路)
然後轉移方程很好寫。用mpmp
mp記錄矩陣,列舉i,j
i,ji,
j,l,
rl,r
l,r的初始值是j
jj,u
uu的初始值是1.若mp[
i][j
−1]!
=mp[
i][j
]mp[i][j-1]!=mp[i][j]
mp[i][
j−1]
!=mp
[i][
j],則l [i
][j]
=l[i
][j−
1]l[i][j]=l[i][j-1]
l[i][j
]=l[
i][j
−1],r
rr的轉移類似。u
uu到後面一邊dpdp
dp一邊轉移。
那現在就開始dpdp
dp了。列舉i,j
i,ji,
j,表示我們現在選的子矩形的左下角。如果mp[
i][j
]!=m
p[i−
1][j
]mp[i][j]!=mp[i-1][j]
mp[i][
j]!=
mp[i
−1][
j],說明我們現在列舉的左下角珂以繼承上面的結果。顯然要先更新u
uu,那我們怎麼繼承其他的部分呢?
綠色表示當前列舉到的點,紅色表示珂以延伸的點。
顯然,我們現在這一行珂以左到2
22,右到4
44,但是上一行到不了這麼遠。
所以我們得到,在往下繼承的時候,左取min
minmi
n,右取max
maxma
x。然後你會發現,這樣考慮每個子矩形的左下角,所有都會被考慮到。正確性。。。感性證明一下,理性證明我也不會證。
**:(以下**中的lef
tleft
left
就是l
ll,rig
htright
righ
t就是r
rr,upup
up就是u uu)
#include
#include
#include
#define n 2010
using
namespace std;
int mp[n]
[n];
int left[n]
[n],right[n]
[n],up[n]
[n];
int n,m;
void
input()
}}void
build()
}}for(
int i=
1;i<=n;i++)}
}//預處理left和right
}void
solve()
int a=right[i]
[j]-left[i]
[j]+1;
int b=
min(a,up[i]
[j])
; ans1=
max(ans1,b*b)
; ans2=
max(ans2,a*up[i]
[j])
;//更新答案
//注意正方形和長方形的區別}}
printf
("%d\n%d\n"
,ans1,ans2);}
main()
洛谷P1169 棋盤製作
懸線法 好像 是可以解決給定矩陣中滿足條件的最大子矩陣的樣子 先就提論題 設 f i j 為從 i,j 點擴充套件最多能達到的最左端的點 color 設l i j 為從 i,j 點擴充套件能達到的最右端的點 color 設up i j 為從 i,j 點能擴充套件到的上界 然後就是 color 從左往...
洛谷 P1169 棋盤製作(懸線法DP)
題目大意 有乙個0,1矩陣。求其中的0,1交錯的最大子正方形矩陣和長方形矩陣的面積。解題思路 求這種最大子矩陣的題目很可能是懸線法。這個矩陣某個格仔 i,j 向左可能延伸到多遠,向右可能延伸到多遠,向上可能延伸到多遠,然後在確定縱向可以向下延伸時候利用轉移公式 up i j up i 1 j 1 l...
P1169 棋盤製作
這裡是題幹 這是什麼優化都沒有的。六次方,爽的一批 include using namespace std int n,m,a 2100 2100 f 100 100 100 100 bool judge int i,int j,int x,int y if k i 2 0 l j 2 1 k i ...