最大子陣——動態規劃DP

wxyfennie發表於2016-05-04


歷屆試題 最大子陣  
時間限制:1.0s   記憶體限制:256.0MB
    
問題描述
  給定一個n*m的矩陣A,求A中的一個非空子矩陣,使這個子矩陣中的元素和最大。

  其中,A的子矩陣指在A中行和列均連續的一塊。
輸入格式
  輸入的第一行包含兩個整數n, m,分別表示矩陣A的行數和列數。
  接下來n行,每行m個整數,表示矩陣A。
輸出格式
  輸出一行,包含一個整數,表示A中最大的子矩陣中的元素和。
樣例輸入
3 3
-1 -4 3
3 4 -1
-5 -2 8
樣例輸出
10
樣例說明
  取最後一列,和為10。
資料規模和約定
  對於50%的資料,1<=n, m<=50;
  對於100%的資料,1<=n, m<=500,A中每個元素的絕對值不超過5000。

-1 -4 3
3 4 -1
-5 -2 8

-1 -4 3
2 0 2
-3 -2 10

1、相當於對一維的最大和的擴充。

2、記錄每一列的sum

3、dp[j][r] - dp[i-1][r]就是對 i~j 行的數值的求和

4、接下來的,相當於對每一行進行最大和求解,也就是對陣列進行最大和求解

5、注意全是負數的情況



#include<iostream>
#include<stdio.h>
using namespace std;
int dp[1005][1005];
int main()
{
    int n,m;
    int k;
    cin>>n>>m;
    for(int j = 0 ; j < m; j++)
    {
        dp[0][j] = 0;
    }
    for(int i = 0; i < n; i ++)
    {
        for(int j = 0 ; j< m ;j ++)
        {
            scanf("%d",&k);
            dp[i][j] = dp[i-1][j] + k;
        }
    }
    int sum = 0;
    int maxx = 0;
    int flag = 0;
    int maxi = -100005;
    for(int i = 0 ; i < n ;i++)
        for(int j = i; j < n ;j++ )
    {
        sum = 0;
        for(int r = 0 ; r < m ;r++)
        {
            if(sum > 0 ) sum += (dp[j][r]-dp[i-1][r]);
            else
            {
                sum = (dp[j][r]-dp[i-1][r]);
                if(!flag && sum > maxi)
                    maxi = sum;
            }
            if(sum > maxx )
            {
                maxx =sum;
                flag = 1;
            }

        }
    }
    if(!flag)
    {
        maxx = maxi;
    }
    cout<<maxx<<endl;
}





相關文章