多維度求解最大子矩陣和(字首 壓縮 DP)

2021-09-10 02:42:06 字數 1394 閱讀 5998

求解此類問題要找規律,首先看一下維度為1時的該問題。

①當維度為1時。

此問題變為求最大連續子段和。此時可以用動態規劃來解決該問題。

動態規劃的思路也很簡單

步驟 1:令狀態 dp[i] 表示以 a[i] 作為末尾的連續序列的最大和(這裡是說 a[i] 必須作為連續序列的末尾)。

步驟 2:做如下考慮:因為 dp[i] 要求是必須以 a[i] 結尾的連續序列,那麼只有兩種情況:

這個最大和的連續序列只有乙個元素,即以 a[i] 開始,以 a[i] 結尾。

這個最大和的連續序列有多個元素,即從前面某處 a[p] 開始 (pfor

(int i=

1;i<=n;i++

) cout<維度為1時非常簡單,那麼維度為2時該怎麼辦呢?

②當維度為2時。

問題變為在乙個矩陣中,找乙個他的子矩陣,該子矩陣是所有子矩陣中和最大的。首先我們想到暴力列舉,那麼複雜度便為o(n * n * m * m * sum),其中若不優化,要求sum也是很困難的。

那麼首先讓我們使用字首來優化求解sum的時間複雜度。

求其中子矩陣的和,肯定需要多次詢問。那麼最好的解決辦法就是字首和。什麼是字首和?設a[i][j]為第j列前i行的和。我們有了求一維度最大連續子段和的經驗,我們可以將維度拆開,列舉其中一維,然後用dp掃另一維,這樣可以讓複雜度降到o(n * m * m )

假設列舉x維度,核心**

ll sqsum

(int x1,

int x2,

int s)

intmain()

} cout<}

有了前兩維,那麼第三維就很容易了。

③當維度為3時。

有了前面的經驗,當維度為3時,列舉兩維中的所有矩陣,對第三維進行掃瞄dp即可。

這時候字首和a[i][j][k]為在k維度下的a[0][j][k]~a[i][j][k]的和加上a[i][0][k] ~a[i][j][k] 的和。既然這樣,那麼再求以(x1,y1)為左上角座標和(x2,y2)為右下角座標的子矩陣的所有元素和。就變得簡單了。這時候的和為 a[x2][y2] - a[x1-1][y2] - a[x2][y1-1] + a[x1-1][y1-1](此時a為字首和的a)同樣這樣可以將最後一維度的o(n^2)的複雜度降為o(n),列舉的複雜度仍沒有變,為o( n * n * m * m),總體複雜度為o(n^5)

核心**

ll sqsum

(int x1,

int y1,

int x2,

int y2,

int s)

intmain()

} cout<}

最大子矩陣 字首和 貪心

給定乙個包含整數的二維矩陣,子矩形是位於整個陣列內的任何大小為1 1或更大的連續子陣列。矩形的總和是該矩形中所有元素的總和。在這個問題中,具有最大和的子矩形被稱為最大子矩形。例如,下列陣列 0 2 7 0 9 2 6 2 4 1 4 1 1 8 0 2 其最大子矩形為 9 2 4 1 1 8 它擁有...

1224 最大子矩陣(字首和)

門2是用的一維字首和,門1的一維字首和 好像有點錯誤。直接cv了 這個 裡,這樣輸入矩陣的方式還是第一次見,字首和是計算的每一列的。include include include include include define inf 999999999 define n 1001 using nam...

最大的和 最大子矩陣和 貪心 字首和 dp

給定乙個包含整數的二維矩陣,子矩形是位於整個陣列內的任何大小為1 1或更大的連續子陣列。矩形的總和是該矩形中所有元素的總和。在這個問題中,具有最大和的子矩形被稱為最大子矩形。例如,下列陣列 0 2 7 0 9 2 6 2 4 1 4 1 1 8 0 2其最大子矩形為 9 2 4 1 1 8它擁有最大...