最大子矩陣(前綴和+貪心)

題目描述

給定一個包含整數的二維矩陣,子矩形是位於整個陣列內的任何大小爲1 * 1或更大的連續子陣列。

矩形的總和是該矩形中所有元素的總和。

在這個問題中,具有最大和的子矩形被稱爲最大子矩形。

例如,下列數組:

0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其最大子矩形爲:

9 2
-4 1
-1 8
它擁有最大和15。

輸入格式

輸入中將包含一個N*N的整數數組。
第一行只輸入一個整數N,表示方形二維數組的大小。
從第二行開始,輸入由空格和換行符隔開的N2個整數,它們即爲二維數組中的N2個元素,輸入順序從二維數組的第一行開始向下逐行輸入,同一行數據從左向右逐個輸入。
數組中的數字會保持在[-127,127]的範圍內。

輸出格式

輸出一個整數,代表最大子矩形的總和。

數據範圍

1≤N≤100

輸入樣例:

4
0 -2 -7 0 9 2 -6 2
-4 1 -4 1 -1

8 0 -2

輸出樣例:

15

題解: 前綴和 + 貪心:
首先我們容易想到,可以枚舉矩陣的左上角(x1, y1)和右下角(x2, y2) ,然後通過二維前綴和算出矩陣和,這樣就可以確定我們所需要的矩陣,但是時間複雜度是O(n4),這樣的複雜度太大了,我們無法解決.所以我們可以換一種思想,貪心處理.問題是我們怎麼貪心了, 大致可以這樣大力貪心:

我們可以將二維求最大子矩陣聯想到一維的求最大子矩陣和的方式,可以先求出每一列的前綴和,
然後倆個for循環枚舉上邊界和下邊界,在用一個for循環來枚舉這個區間內的每一列,因爲我們已經求出每一列的前綴和了,所以這倆個邊界之間的每一列之和我們是知道的, 所以就可以用一維的方法來做了。

#include<iostream>
#include<algorithm>
using namespace std;
int a[110][110];
int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
        {
        cin >> a[i][j];
        a[i][j] += a[i - 1][j];  //求出每一列的前綴和
        }
    int Max = -1e9;
    for(int i = 1; i <= n; i++){
        for(int j = i; j <= n; j++){
            int now = 0;
            for(int k = 1; k <= n; k++){
                now = max(now, 0) + a[j][k] - a[i - 1][k];  //如果now小於0了,如果加上的話數值會變小,所以乾脆就不用加了
                Max = max(Max, now);
            }
        }
    }
    cout << Max << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章