您的位置:首页 > 其它

hdu 1081 To The Max 最大子矩阵和(dp)

2014-07-30 15:20 471 查看
题意:

给定一个n*n的矩阵,求所有的子矩阵中,输出最大子矩阵和最大是多少。(矩阵和是指矩阵中所有元素相加所得到的值)

题解:

在解这道题之前,我们需要了解最大连续子序列和。给定一个序列,我们求最大连续子序列和的方法是:先令k=0,然后遍历序列,将序列元素加到k上;当k为负数时,k=0(因为使k变为负数的数必定是负数,最大结果肯定不能包含这个元素,假设包含这个元素,那么必须在这个元素之前要有够大的序列和大于这个元素,而根据k的性质是不存在这样的序列的,所以必定不能包含这个元素)。以这种方式到序列最后,那么其中出现的最大的k就是最大连续子序列和。

这道题是先用sum[i][j]=e[1][j]+e[2][j]+..ei][j],那么i行到k行,在j列上的元素和就是f[j]=sum[k][j]-sum[i-1][j];我们枚举子矩阵的高k和开始行i,怎么求宽度?我们得到一个序列f[j]=sum[i+k-1][j]-sum[i-1][j],那么求高度为k,开始行为i的最大子矩阵和就相当于求这个序列f的最大连续子序列和了。那么时间复杂度压缩到了O(n^3)

代码:

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <ctime>
#include <vector>
#include <cmath>
#include <cstdlib>
using namespace std;

const int maxn=110;
const int INF=1e8;
int e[maxn][maxn];
int sum[maxn][maxn];
int f[maxn],dp[maxn];
int fun(int n)//用dp求f数组中最大连续子串和
{
    int i,j,k=0,ans=-INF;
    for(i=1;i<=n;i++)
    {
        k+=f[i];
        ans=max(ans,k);
        if(k<0)k=0;
    }
    return ans;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int i,j,k,ans=-INF;
        memset(sum,0,sizeof(sum));
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                scanf("%d",&e[i][j]);
                sum[i][j]=sum[i-1][j]+e[i][j];
            }
        }
        for(k=1;k<=n;k++)//枚举子矩阵高度
        {
            for(i=1;i<=n-k+1;i++)//子矩阵开始行
            {
                for(j=1;j<=n;j++)
                    f[j]=sum[i+k-1][j]-sum[i-1][j];
                ans=max(ans,fun(n));
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: