有一天,小貓rainbow和freda來到了湘西張家界的天門山玉蟾宮,玉蟾宮宮主藍兔盛情地款待了它們,並賜予它們一片土地。
這片土地被分成n*m個格仔,每個格仔裡寫著'r'或者'f',r代表這塊土地被賜予了rainbow,f代表這塊土地被賜予了freda。
現在freda要在這裡賣萌。。。它要找一塊矩形土地,要求這片土地都標著'f'並且面積最大。
但是rainbow和freda的oi水平都弱爆了,找不出這塊土地,而藍兔也想看freda賣萌(她顯然是不會程式設計的……),所以它們決定,如果你找到的土地面積為s,它們每人給你s兩銀子。
輸入格式:
第一行兩個整數n,m,表示矩形土地有n行m列。
接下來n行,每行m個用空格隔開的字元'f'或'r',描述了矩形土地。
輸出格式:
輸出乙個整數,表示你能得到多少銀子,即(3*最大'f'矩形土地面積)的值。
輸入樣例#1:
5 6r f f f f f
f f f f f f
r r r f f f
f f f f f f
f f f f f f
輸出樣例#1:
45對於50%的資料,1<=n,m<=200
對於100%的資料,1<=n,m<=1000
模板最大子矩陣...
這道題需要用到乙個東西,叫做單調棧.於是乎就在這裡做乙個補充.
首先,我們需要將這個問題轉換一下:
圖中是乙個 4×6 的矩形,畫出紅色的是我們要找到的區域。
然後我們可以將這個圖轉化:
因為我們要找的是矩形,所以它一定是以 某個行元素開始的,如果枚舉行的時候,我們會發現:
對於第一行:
對於第二行:
第三行:
第四行:
那麼我們原始矩形可以變成如下的形式的資料:
然後此時的話,就是給你若干個柱狀圖,然後要你求其中的最大矩形:
!(那麼明顯是可以 n^2 列舉的,但是這樣會爆.
那麼怎樣才能在 o(n) 的時間複雜度下處理出這個東西呢?
我們使用單調棧.
單調棧,顧名思義,就是裡面元素滿足單調性質的乙個棧.因為我們可以很容易推出來,當我們乙個矩形的高度可以計算的時候,選擇的區域裡面所有條狀的高度都要大於等於當前這個高度.
然後我們看具體操作:
乙個 l 陣列 ,代表當前這個高度,我們可以達到的最左邊的點.
乙個 r 陣列 ,同理.
我們需要遍歷兩遍,一遍處理當前的 l 陣列.一遍處理 r 陣列.
1)先將乙個 (0,0) 的元素推進棧中.
2)每一次我們遍歷到的點就是我們現在要處理的.
3)先一直把棧中高於當前選擇的節點的高度的點都彈出.
(這個應該很好理解.因為只有低於我的點才是邊界).
4)如果棧已經空了,就把 l [ i ] 賦成 1.
5)否則,則賦成當前的棧頂+1 (棧頂已經小於我們了).
然後的話 r 陣列是一樣的處理方式.
然後每一次的以當前我們的高度處理出來的最大面積就是:
\[height[i]×(r[i]-l[i]+1)
\]然後統計答案即可.
然後這道題題目就用這個模板處理出來每一行即可.
#includeusing namespace std;
const int maxn=1008;
int c[maxn][maxn];
int n,m,ans=-1;
int a[maxn][maxn];
int pre(int x,int y)
void getans(int x)
,r[maxn]=;
for(int i=1;i<=m;i++)
while(!s.empty()) s.pop();
for(int i=m;i>=1;i--)
while(!s.empty()) s.pop();
for(int i=1;i<=m;i++)
}int main()
for(int i=1;i<=m;i++)
pre(1,i);
for(int i=1;i<=n;i++)
getans(i);
cout<
return 0;
}
P4147 玉蟾宮 單調棧
有一天,小貓rainbow和freda來到了湘西張家界的天門山玉蟾宮,玉蟾宮宮主藍兔盛情地款待了它們,並賜予它們一片土地。這片土地被分成n m個格仔,每個格仔裡寫著 r 或者 f r代表這塊土地被賜予了rainbow,f代表這塊土地被賜予了freda。現在freda要在這裡賣萌。它要找一塊矩形土地,...
玉蟾宮 洛谷P4147
題目描述 有一天,小貓rainbow和freda來到了湘西張家界的天門山玉蟾宮,玉蟾宮宮主藍兔盛情地款待了它們,並賜予它們一片土地。這片土地被分成nm個格仔,每個格仔裡寫著 r 或者 f r代表這塊土地被賜予了rainbow,f代表這塊土地被賜予了freda。現在freda要在這裡賣萌。它要找一塊矩...
洛谷P4147 玉蟾宮
傳送門給定乙個 n m 的 0 1 矩陣,求最大子矩陣 滿足矩陣內所有元素均為 1 輸出矩陣大小 3 懸線法,最大子矩陣板子題 也可以單調棧和並查集,但是窩不會 維護三個值 l i j 和 r i j up i j 分別代表當前點 i,j 向左最長的延伸到的點位置,向右最長的延伸到的點位置,向上最長...