zoukankan      html  css  js  c++  java
  • 【动态规划】最大连续子序列和,最大子矩阵和,最大m子段和

    1.最大字段和问题

    求一个序列最大连续子序列之和。

    例如序列[-1,-2,-3,4,5,-6]的最大子段和为4 + 5 = 9。

    ①枚举法

    int MaxSum(int n,int *a){
        int sum = -0x3f3f3f3f;
        for(int i=0;i<n;i++){
            int b = 0;
            for(int j=i;j<n;j++){
                b += a[j];
                sum = b > sum ? b : sum;
            }
        }
        return sum;
    }

     ②动态规划

    解题思路:

    第一步:设b[ j ] 为 1到 j 的最大连续子序列之和。

    第二步:因为b[ j ] 为以a[ j ]结尾的最大连续子序列之和,因此有两种可能

      1.b[ j ] = a[ j ]

      2.b[ j ] = b[ j - 1 ] + a[ j ]

    因此我们可以得到递推方程,

    b[ j ] = max{ a[ j ], b[ j  - 1] + a[ j ] } = max { 0 , b[ j - 1 ]} + a[ j ]

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

    2.引申:两个连续序列的最大字段和问题

    求两个等长的序列的最大重叠连续子序列之和

    例,第一个序列为[-1,-2,-3,4,5,-6],第二个序列为[1,2,4,4,5,-6],则 MAX = ( 4 + 5) + (4 + 5) = 19

    2与1的区别在于,原本只有一个序列,现在变成两个,但是求的是最大重叠连序列之和,所以可以将两个序列加起来变成一个序列。

    ①枚举法

    ②动态规划

    解题思路:

    设b[ j ] 为 1到 j 的最大重叠连续子序列之和。

    若b[ j - 1 ] >= 0 ,

      则 b[ j ] = b [ j - 1 ] + a[ 0 ][ j ] +  a[ 1 ][ j ];

      否则 b[ j ] = a[ 0 ][ j ] +  a[ 1 ][ j ]

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

    3.最大子矩阵之和

    给定矩阵A,求其子矩阵各元素之和的最值

    若将矩阵的行看作是一个个的连续序列,则与2问题不同的是,

      第一,可能不只一个连续序列(矩阵的行)相加,

      第二,需要枚举子矩阵的初始行R0,和结束行R1

    ①枚举法

    ②动态规划

    //求 r0行到r1行 第i列元素的和 
    int sum_r(int r0, int r1, int i){
        int sum = 0;
        for(int r=r0;r<=r1;r++)
            sum += a[r][i];
        return sum;
    }
    //求最大子矩阵和
    int MaxSum(){
        int sum = -0x3f3f3f3f;
        for(int r0=0;r0<m;r0++){//枚举初始行
            for(int r1=r0;r1<m;r1++){//枚举结束行
                int b = 0;
                for(int i=0; i<n; i++){//这个循环使用问题1中的算法
                    if(b>=0)
                        b+=sum_r(r0,r1,i);//第r0行到第r1行 第i列元素和
                    else
                        b=sum_r(r0,r1,i);
                    
                    sum = sum > b? sum : b;
                }
            }
        }
        return sum;
    }

    我们能够注意到,上面的程序,需要我们写一个计算第r0行到第r1行第i列的元素和的函数sum_r( ),但是我们需要频繁调用这个函数,可以用一个数组来记录计算结果,这一步可以在我们读入数据的时候进行。

    专门建立一个二维数组,col [ i ][ j ],记录第 i 列,前 j 个元素的和。

    所以,MaxSum函数中,b += sum_r(r0, r1, i ),可以替换成

    b += col[ i ][ r1 ] - col[ i ][ r0 - 1 ]

    最终代码

    int MaxSum(){
        int sum = -0x3f3f3f3f;
        for(int r0=0;r0<m;r0++){
            for(int r1=r0;r1<m;r1++){
                int b = 0;
                for(int i=0; i<n; i++){
                    if(b>=0)
                        b+=col[i][r1] - col[i][r0 - 1];
                    else
                        b=col[i][r1] - col[i][r0 - 1];
                    
                    sum = sum > b? sum : b;
                }
            }
        }
        return sum;
    }

     4.最大m字段和问题

  • 相关阅读:
    使用牛顿迭代法和二分法求解一个数的平方根(python语言实现)
    厄拉多塞筛法和普通方法求素数表(python实现)
    使用辗转相除法求两个数的最大公因数(python实现)
    我在博客园第一篇博文
    Linux安装maven
    MyBatis基础入门
    Maven的使用入门
    nginx的简单使用和使用nginx在windows上搭建tomcat集群
    后端程序员如何玩转AJAX
    Servlet3.0文件上传
  • 原文地址:https://www.cnblogs.com/woxiaosade/p/10327587.html
Copyright © 2011-2022 走看看