最大全0/1子矩阵的探究
最大全0/1子矩陣的探究
by MedalPluS
??【問題模型】
? ? 給定一個n*n的矩陣,求矩陣中面積最大的一個值全是0或1的子矩陣
? 【分析】
? ? (這里n*n完全可以改為n*m,但由于種種原因,等下代碼里是n*n)
? ? 首先很容易想到一種解法,枚舉這個子矩陣的左上方,和右下方,然后暴力統計,這樣時間復雜度O(N6),這種做法很廣泛
? ? 這肯定是不能滿足我們的需求,那么應該怎么辦呢?我們發現O(n2)的時間浪費在統計上,我們可以使用前綴和的手段,預處理
? ? 這樣時間復雜度O(n4),還是很垃圾
? ? 在暴力種種優化都不行的時候,想一想貪心或者數學或者DP把!——無名氏
? ? 貪心:這肯定是不對的
? ? DP:轉移方程太難推出
? ? 數學:這個我可以
? ? ? ? ? 對于3*3的矩陣
? ? ? ? ? 0 1 1
? ? ? ? ? 1 0 0
? ? ? ? ? 1 1 1
? ? ? ? ? 求全1矩陣
? ? ? ? ? 我們可以逐行算!
? ? ? ? ? 比如說設f(i)表示第i列的已經連續的全1的子矩陣的長度
? ? ? ? ? 處理第一行,可以發現f(1)=0,f(2)=1,f(3)=1
? ? ? ? ? 映射到數軸上,可以發現是這樣的:
? ? ? ? ??
? ? ? ? ? 面積最大全1矩陣很明顯是1+1=2,記錄下來,發現了沒?其實就是直方圖最大面積
? ? ? ? ? 繼續處理第二行,此時f(1)=1,f(2)=0,f(3)=0
? ? ? ? ? 映射到數軸上,可以發現是這樣的:
? ? ? ? ??
? ? ? ? ? 最大面積為1,而沒有原來的2小,所以不記錄
? ? ? ? ? 處理第三行,此時f(1)=2,f(2)=1,f(3)=1
? ? ? ? ? 映射到數軸上
? ? ? ? ??
? ? ? ? ? ?輕易地算出最大面積為3,比2大,更換
? ? ? ? ? 掃描結束,最大值為3,而正好是答案
? 【實現】
? ? ? 那么具體應該如何實現呢?
? ? ? 同上,設f(),再設l(),r(),表示第i行以f(i)為最大值的直方圖的左端點l(i)和右端點r(i)
? ? ? 顯然,這行的結果為f(i)*((r(i)-l(i)+1)
? ? ? ?每次累計最大值
? ? ? 輸出即可
? ?【代碼】
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 const int maxn=2001; 6 7 int a[maxn][maxn],n,ans; 8 int l[maxn],r[maxn],b[maxn]; 9 10 int main(){ 11 int i,j; 12 scanf("%d",&n); 13 for(i=1;i<=n;i++){ 14 for(j=1;j<=n;j++){ 15 scanf("%d",&a[i][j]); 16 if(!a[i][j])b[j]++;//注意這里指的是全0子矩陣,如果是求全1子矩陣的話,應該改為if(a[i][j])b[j]++;想想為什么 17 else b[j]=0; 18 } 19 for(j=1;j<=n;j++)//求出l 20 { 21 l[j]=j; 22 while(l[j]-1>=1 && b[l[j]-1]>=b[j]) 23 l[j]=l[l[j]-1]; 24 } 25 for(j=n;j>=1;j--)//求出r 26 { 27 r[j]=j; 28 while(r[j]+1<=n && b[r[j]+1]>=b[j]) 29 r[j]=r[r[j]+1]; 30 } 31 for(j=1;j<=n;j++)//算出面積 32 if(b[j] && ans<b[j]*(r[j]-l[j]+1)) 33 ans=b[j]*(r[j]-l[j]+1); 34 } 35 printf("%d",ans); 36 return 0; 37 }?
轉載于:https://www.cnblogs.com/maopengsen/p/4430775.html
總結
以上是生活随笔為你收集整理的最大全0/1子矩阵的探究的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows8 正式版最简单的去除桌面
- 下一篇: Exchange Server 2013