最大子矩陣(普通和01)

2021-10-07 14:29:15 字數 2285 閱讀 3129

01矩陣(單個矩陣值為0或1)

**:例題:poj 1074

求出其中最大的子矩陣

答案是:

9 2-4 1

-1 8

最大和是15

我們先想想如果不是矩陣,是乙個陣列,求其中連續的最長一段,咋做?

我們用b[i]來表示a[0]…a[1]的最大子段和

那麼b [ i ] =max ( b [i - 1 ] + a [ i ], a [ i ] )

當a[n] 大於dp[n-1](前n-1個元素序列的最大子段和)。此時捨棄前面的子段和,即斷開。

否則的話,把a[n]連線到前n-1個元素序列的最大和子段上,即dp[n] = dp[n-1] + a[n]

int

maxsum

(int n,

int*a)

return sum;

}

二維矩陣排列方式如圖

參考題解

如果紅色是我們要找的最大子矩陣

那和就是:(a[q][i]+…+a[p][i],a[q][i+1]+…+a[p][i+1],…,a[q][j]+…a[p][j])=(sum1,sum2,…,sumn)

sum也就是每一列的相同行數相加

這不也是sun的一維陣列,那其實就是乙個一維陣列的最大子段問題

如果把二維陣列看成是縱向的一維陣列和橫向的一維陣列

#include

#include

using

namespace std;

intmaxsub

(int a,

int n)

return max;

}int

main()

} cout << maxsubrec << endl;

return0;

}

參考題解

其實就是沒有負數情況

我一開始想的是將最大子矩陣的**中,如果乙個數為0就賦值為-10000(這樣程式就肯定不會選擇這個塊)

但是這樣會超時

針對01矩陣我們可以這麼想:

每乙個單元格的值等於它所在列的連續1的數量,如果當前行為1,則當前行的值就等於上一行加1,如果當前行為0,則他的值也是0

我們掃瞄每一行,求出這一行中可形成的矩形最大面積,然後去最大情況即可

然後我們要用到乙個單調遞減的單調棧,

如果棧為空或者當前元素大於等於棧頂元素,則入棧

若棧非空且當前元素小於棧頂元素,則將棧頂彈出,更新面積最大值,直到棧空或者遇到第乙個大於等於當前元素

將最後乙個出棧的棧頂元素(最後乙個大於當前元素的)向左右延伸,修改其值,併入棧。

核心都是對於每個高度為h的矩形,找到最左高度大於等於它的位置,和最右的位置。

我們看第三行:

0 1 3 2 0 0 0

0先入棧,然後1入棧,然後3入棧,然後到2時,2<3,計算此時的矩陣面積=(4-3) * 3=3,此時最大面積是3,然後將值3改為2,此時就是0 1 2 2 ,然後0<2,計算此時面積 = (5-3) * 2=4,最大面積就是4,一次類推,都是按照這個操作

#include

#include

#include

#include

using

namespace std;

intmain()

a[n+1]

=-1;

//設最後元素為最小值,以最後讓棧內元素出棧

for(j=

1;j<=n+

1;j++

)else

st.push

(top)

;//將最後一次出棧的棧頂元素延伸併入棧

a[top]

=a[j]

;//修改其對應的值 }}

}printf

("%d\n"

,ans);}

return0;

}

最大子段和 最大子矩陣和

給出n個整數序列 可能為負數 組成的序列a1,a2,an,求該序列形如 的子段和的最大值。當所有整數均為負數時,定義最大子段和為0。多測試用例。每個測試用例佔2行 第一行是序列的個數n 0 n 10000 第二行是n個整數。為每個測試用例輸出一行結果 最大子段和。6 2 11 4 13 5 2 31...

最大子矩陣和

前言 今天花了很長時間,看了無數人寫的帖子,但是幾乎沒有人把這個問題一下子說得很清楚,所以,我把這個問題按照自己的思路寫出來,希望能夠把這個問題講清楚。問題 求乙個m n的矩陣的最大子矩陣和。比如在如下這個矩陣中 0 2 7 0 9 2 6 2 4 1 4 1 1 8 0 2 擁有最大和的子矩陣為 ...

最大子矩陣和

前言 今天花了很長時間,看了無數人寫的帖子,但是幾乎沒有人把這個問題一下子說得很清楚,所以,我把這個問題按照自己的思路寫出來,希望能夠把這個問題講清楚。問題 求乙個m n的矩陣的最大子矩陣和。比如在如下這個矩陣中 0 2 7 0 9 2 6 2 4 1 4 1 1 8 0 2 擁有最大和的子矩陣為 ...