題目104:最大和

題目鏈接:

http://acm.nyist.net/JudgeOnline/problem.php?pid=104

描述

給定一個由整數組成二維矩陣(r*c),現在需要找出它的一個子矩陣,使得這個子矩陣內的所有元素之和最大,並把這個子矩陣稱爲最大子矩陣。
例子:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其最大子矩陣爲:

9 2
-4 1
-1 8
其元素總和爲15。

輸入

第一行輸入一個整數n(0<n≤100),表示有n組測試數據;
每組測試數據:
第一行有兩個的整數r,c(0<r,c≤100),r、c分別代表矩陣的行和列;
隨後有r行,每行有c個整數;

輸出

輸出矩陣的最大子矩陣的元素之和。

樣例輸入

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

樣例輸出

15

算法思想:

算法思想:考慮求一維的數組連續子序列和最大值,算法很簡單,典型的動態規劃,使用max_sum表示從第一數到目前的最大和,sum是某段區間的和,如果sum<0,那麼sum沒有利用價值了,把sum=0,否則就繼續往上加。
max_sum=max((sum+=a[i])<0?0:sum,max_sum);
二維的問題,其實可以轉化爲一維的問題。
這個轉化需要一個技巧,如果不使用這個技巧來做會稍微複雜些。二維問題其實就相當於多個一維問題的求解。
首先我們要注意到二維子矩陣在選取的時候是個矩陣,聯繫一個我們經常會用到的技巧:但我們需要頻繁計算一個數據任意一個區間
的和的時候,我們會預先把這個數組使用啊a[i]=a[i]+a[i-1]的方式把它記錄的值變爲數組到這個位置的和,這樣的好處就是任意一個區間[i,j]的和就可轉化爲了a[j]-a[i-1]。
在這裏我們依然採用這樣的技巧。我們把這個矩陣記錄的值對於每個列向量都做上述改變。
然後我們就發現,但我們選取任意的連續行進行組合的時候,這個行區間對於的列的值的和都可以用上述方法快速獲得,那麼對於每個列的和又會變爲一個求一維連續區間最大和問題了。到此這個問題就可以以O(n^2)的複雜度解決了。

源代碼

/*
Author:楊林峯
Date:2017.11.28
NYOJ(104):最大和
*/
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    int n, r, c, maxnum, sum, map[105][105];
    memset(map, 0, sizeof(map));
    cin >> n;
    while (n--)
    {
        cin >> r >> c;
        for (int i = 1; i <= r; i++)
        {
            for (int j = 0; j < c; j++)
            {
                cin >> map[i][j];
                map[i][j] += map[i - 1][j];  //第i行存入的數據是前i行對應數據的和
            }
        }
        int k;
        /*求解每個組合的一維問題解,其最大值即爲該矩陣的解*/
        for (k = 1, maxnum = map[1][0]; k <= r; k++)
            for (int i = k; i <= r; i++)
            {
                /*求解一維問題*/
                sum = 0;
                for (int j = 0; j < c; j++)
                {
                    sum += map[i][j] - map[k - 1][j];
                    if (sum < 0)
                    {
                        sum = 0;
                    }
                    else if (sum > maxnum)
                    {
                        maxnum = sum;
                    }
                }
            }
        cout << maxnum << endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章