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 擁有最大和的子矩陣為 ...