第九章 動態規劃-1282:最大子矩陣

【題目描述】
已知矩陣的大小定義爲矩陣中所有元素的和。給定一個矩陣,你的任務是找到最大的非空(大小至少是1 × 1)子矩陣。

比如,如下4 × 4的矩陣

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(0<N≤100)。再後面的若干行中,依次(首先從左到右給出第一行的N個整數,再從左到右給出第二行的N個整數……)給出矩陣中的N2個整數,整數之間由空白字符分隔(空格或者空行)。已知矩陣中整數的範圍都在[−127,127]。

【輸出】
輸出最大子矩陣的大小。

【輸入樣例】
4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2

【輸出樣例】
15
————————————————
思路:假設所求N*N的矩陣的最大子矩陣是從i列到j列,q行到p行,如下圖所示

a[1][1]  a[1][2]  ······  a[1][i]  ······  a[1][j]   ······  a[1][n]

a[2][1]  a[2][2]  ······  a[2][i]  ······  a[2][j]   ······  a[2][n]

······

a[q][1]  a[q][2]  ······  a[q][i]   ······  a[q][j]   ······  a[q][n]

······

a[p][1]  a[p][2]  ······  a[p][i]   ······  a[p][j]   ······  a[p][n]

······

a[n][1]  a[n][2]  ······  a[n][i]  ······  a[n][j]  ······   a[n][n]

最大子矩陣就是圖示劃線部分,如果把最大子矩陣同列的加起來,我們可以得到一個一維數組{a[q][i]+······+a[p][i] , ······ ,a[q][j]+······+a[p][j] } ,現在我們可以看出,這其實就是一個一維數組的最大子段問題。即把二維數組看成是縱向的一維數組和橫向的一維數組。
想找到n個數的最大子段和,先要找到n-1個數的最大子段和。我們用sum來表示t[0]…t[i]的最大子段和,sum有兩種情況:(1)最大子段一直到t[i]  (2)以t[i]爲首的新的子段。可以得到sum的狀態轉移方程:sum=max{sum+t[i],t[i]}。最終我們得到的最大子段和爲max{sum, 0<=i<n}

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
#define N 1001
using namespace std;
int a[N][N],f[N];
int maxArray(int t[],int n)
{
    int sum = 0,maxx = -INF;
    for(int i = 1;i <= n;i++)
    {
        if(sum > 0)
            sum += t[i];//若t[i]+sum[i-1]會減小
        else
            sum = t[i];// 則以t[i]爲首另起一個子段
        if(sum > maxx)
            maxx = sum;
    }
    return maxx;
}
int main()
{
    int n;
    cin >> n;
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)
            cin >> a[i][j];
    int maxx = -INF;
    for(int i = 1;i <= n;i++)
    {
        memset(f,0,sizeof(f));
        for(int j = i;j <= n;j++)
        {
            for(int k = 1;k <= n;k++)
                f[k] += a[j][k];
 
            int temp = maxArray(f,n);
            if(temp > maxx)
                maxx = temp;
        }
    }
    cout << maxx << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章