码迷,mamicode.com
首页 > 其他好文 > 详细

最大子段和问题及其推广

时间:2015-07-12 15:38:23      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:

实在是太颓废了,所以开始写点东西吧。。。。

最大子段和: 给定N个数(可能为负整数)组成的序列a1...an,求该序列形如∑ak(i<=k<=j)的子段和的最大值。当所有整数均为负整数时定义其最大的子段和为0.

依据题意我们可以确定 最优值为max(0,max∑ak(i<=i<=j<=n)); 若我们令b[j] = max∑ak(1<=i<=j)是从序列a的第i个数到第j个数的最大和,那么我们最后的答案就是找出b数组里面记录的最大的那个值就是答案。由b[j]的定义可以知道b[j-1]>0时,b[j] = b[j-1]+a[j]否则b[j] = a[j];由此得出递推式b[j] = max(b[j-1]+a[j],a[j]) (1<=j<=n)

代码如下

技术分享
 1 int Maxsum1(int n,int *a)
 2 {
 3     int sum = 0,b = 0;
 4     for(int i=1;i<=n;i++){
 5         if(b>0) b += a[i];
 6         else b = a[i];
 7         if(b > sum ) sum = b;
 8     }
 9     return  sum;
10 }
View Code

最大子段和的推广

(1)最大子矩阵:给定一个m行n列的整数矩阵A,求其元素和最大的子矩阵

很明显最大子矩阵和的问题是最大子段和的问题向二维的推广,我们用数组a[1:m][1:n]表示给定的矩阵A 其子数组a[i1:i2][j1:j2]表示左上角和右下角的行列坐标分别为(i1,j1)(i2,j2)的子矩阵 其个各个元素之和 记为 S(i1,i2,j1,j2)= ∑∑a[i][j] (i1<=i<=i2,j1<=j<=j2) 那么ans = Max S(i1,i2,j1,j2) (1<=i1<=i2<=m,1<=j1<=j2<=n)

我们可以令t(i1,i2) = maxS(i1,i2,j1,j2)(i<=j1<=j2<=n) = Max∑∑a[i][j] 同样我们令b[j] = ∑a[i][j](i1<=i<=i2) 于是 t(i1,i2) = max∑b[j](1<=j1<=j2<=n) 这又回到了一维的情况于是我们可以得到如下代码

技术分享
 1 int Maxsum2(int m,int n,int a[105][105] )
 2 {
 3     int sum = 0;
 4     int b[105];
 5     for(int i=1;i<=m;i++){
 6         memset(b,0,sizeof(b));
 7         for(int j=i;j<=m;j++){
 8             for(int k=1;k<=n;k++) b[k] += a[j][k];
 9             int Max = Maxsum1(n,b);
10             if(Max > sum) sum = Max;
11         }
12     }
13     return sum ;
14 }
View Code

最大子矩阵在poj上面有原题目 题号是1050 代码如下

技术分享
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int M = 105;

int a[M][M];

int Maxsum1(int n,int *a)
{
    int sum = 0,b = 0;
    for(int i=1;i<=n;i++){
        if(b>0) b += a[i];
        else b = a[i];
        if(b > sum ) sum = b;
    }
    return  sum;
}

int Maxsum2(int m,int n,int a[105][105] )
{
    int sum = 0;
    int b[105];
    for(int i=1;i<=m;i++){
        memset(b,0,sizeof(b));
        for(int j=i;j<=m;j++){
            for(int k=1;k<=n;k++) b[k] += a[j][k];
            int Max = Maxsum1(n,b);
            if(Max > sum) sum = Max;
        }
    }
    return sum ;
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
            scanf("%d",&a[i][j]);
    }
    printf("%d\n",Maxsum2(n,n,a));




    return 0;
}
View Code

 

最大子段和问题及其推广

标签:

原文地址:http://www.cnblogs.com/lmlyzxiao/p/4640901.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!