LA3029 矩陣中求子矩陣最大問題

2021-06-18 06:50:02 字數 1363 閱讀 1319

la3029:題意給你乙個矩陣,每個單元格要麼為空,要麼為滿,求全是空的最大子矩陣的格仔數*3.

最樸素的演算法是列舉所有的子矩陣的左上角的點和右下角的點,這樣就能確定乙個矩形,然後再遍歷這個矩陣,看矩陣是否全是空。複雜度大概是o(m^2*n^2)

通過掃瞄法,每次維護left[i][j],right[i][j],up[i][j],可以簡化到o(mn)

曾經有想過只維護left,像字首那樣,不過後來發現如果這樣的話,不能保證每次這個單元格上面全是空,所以還得維護right。

left[i][j]表示某個點的向左運動極限,right[i][j]表示某個點向右運動極限,都用列的編號來表示。up[i][j]表示向上的運動長度,用數字的表示。

這樣子矩陣就能表示為(right[i][j]-left[i][j]+1)*up[i][j],求最大值即可.

轉移方程:

第一行:

由於不受上面一行的限制:

如果為空:left[i][j]=lo+1,right[i][j]=ro-1,up[i][j]=1;

不是第一行:

如果為滿:left[i][j]=0,right[i][j]=n,up[i][j]=0;

如果為空:left[i][j]=max(lo+1,left[i-1][j]),right[i][j]=min(ro-1,right[i-1][j]),up[i][j]=up[i-1][j];

**:

#include#include#include#include#include#include#include#include#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

#define maxn 1005

#define inf 0xfffffff

#define mem(a,b) memset(a,b,sizeof(a))

#define for(i,s,t) for(int i=s;i<=t;i++)

#define ull unsigned long long

#define ll long long

using namespace std;

int map[maxn][maxn],left[maxn][maxn],right[maxn][maxn],up[maxn][maxn];

int main()

else

else

right[i][j]=min(ro-1,right[i-1][j]);

}ans=max(ans,(right[i][j]-left[i][j]+1)*up[i][j]);}}

printf("%d\n",ans*3);

}return 0;

}

LA3029最大子矩陣

題意 給你乙個n m的矩陣 每個格仔不是 f 就是 r 讓你找乙個最大的 f 矩陣,輸出他的面積 3。思路 比較經典的題目了,現在想起來比較好想,以前的話想著很費勁,最早先用瓶頸法在杭電上過了乙個資料範圍比較小的,今天的這個目測瓶頸法過不去,瓶頸法的時間複雜度是o n 3 的,今天的這個我們可以用另...

列舉(最大子矩陣,LA 3029)

感覺列舉的問題想要優化就一定要一邊列舉一邊維護些東西,或者要預處理之類的。記得以前做了一道題 唯一的不同是求周長最長。做的時候參考了這道題,也是列舉右下角,然後用單調棧維護左上角。在那題中隨著j的增大,並不會影響單調棧內元素的單調性。然而在這題裡,隨著j的增大,越後面的元素增長得越快,因此後面的小的...

矩陣中求子矩形

有乙個 n的矩形,其中每個元素只可能是0or1。比如如下矩陣a 1 1 0 0 0 0 1 1 1 0 1 0 1 1 0 1其中a 0 0 a 0 1 a 3 0 a 3 1 這四個元素恰好是乙個長方形的四個角,且每個元素都是1.因此稱這四個元素圍成了乙個子矩形。現在需要判斷,給定的矩陣a中,判斷...