1. 程式人生 > >最大子矩陣和---(dp)

最大子矩陣和---(dp)

題目描述

一個M*N的矩陣,找到此矩陣的一個子矩陣,並且這個子矩陣的元素的和是最大的,輸出這個最大的值。

例如:3*3的矩陣:

-1 3 -1

2 -1 3

-3 1 2

和最大的子矩陣是:

3 -1

-1 3

1 2

Input

第1行:M和N,中間用空格隔開(2 <= M,N <= 500)。  第2 - N + 1行:矩陣中的元素,每行M個數,中間用空格隔開。(-10^9 <= M[i] <= 10^9)

Output

輸出和的最大值。如果所有數都是負數,就輸出0。

Sample Input

3 3
-1 3 -1
2 -1 3
-3 1 2

Sample Output

7

思路

題目的意思是在整個矩陣中找一個子矩陣使得該子矩陣的每個數的和可以達到最大,這個子矩陣可以是一個數,我們可以使用dp,先從行開始確定,再確定列,具體的解釋見程式碼的備註。

程式碼

#include<stdio.h>
#include<iostream>
using namespace std;
#include<algorithm>
#include<string.h>
const int maxn=505;
__int64 sum,ans;
int dp[maxn][maxn];
int main()
{
    int n,t,m;
    memset(dp,0,sizeof(dp));
    scanf("%d%d",&m,&n);
    for(int j=1;j<=n;j++)
        for(int i=1;i<=m;i++){
            scanf("%d",&t);   //使得dp這個陣列中第二行表示的是一到二行的每列之和,方便求sum
            dp[j][i]=t+dp[j-1][i]; 
        }
    ans=0;
    for(int i=1;i<=n;++i)//確定最大子矩陣在哪兩行之間
        for(int j=i;j<=n;++j){ //當j=2時表示在求第二行和第一行之間最大的子矩陣和
            sum=0;
            for(int k=1;k<=m;++k){ //表示列
                sum=max((__int64)0,sum+dp[j][k]-dp[i-1][k]);//求和,若小於0,則sum還是0
                ans=max(ans,sum);//用ans記錄最大的sum值
            }
        }
    printf("%I64d\n",ans);
    return 0;
}