• 动态规划——求最大子序列


    1.先来分析一维的:

    #include<stdio.h>
    int main()
    {
        int t,m,n,sum,maxSum;
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d",&n,&sum);
            maxSum=sum;
            while(--n)
            {
                scanf("%d",&t);
                if(sum<0) sum=t;
                else sum+=t;
                if(maxSum<sum) maxSum=sum;
            }   
            printf("%d\n",maxSum);
        }
        return 0;
    }        

    这里需要两个结论。首先,对于array[1...n],如果array[i...j]就是满足和最大的子串,那么对于任何k(i<=k<=j),我们有array[i...k]的和大于0。因为如果存在k使得array[i...k]的和小于0,那么我们就有array[k+1...j]的和大于array[i...j],这与我们假设的array[i...j]就是array中和最大子串矛盾。

    其次,我们可以将数组从左到右分割为若干子串,使得除了最后一个子串之外,其余子串的各元素之和小于0,且对于所有子串array[i...j]和任意k(i<=k<j),有array[i...k]的和大于0。此时我们要说明的是,满足条件的和最大子串,只能是上述某个子串的前缀,而不可能跨越多个子串。我们假设array[p...q],是array的和最大子串,且array[p...q],跨越了array[i...j],array[j+1...k]。根据我们的分组方式,存在i<=m<j使得array[i...m]的和是array[i...j]中的最大值,存在j+1<=n<k使得array[j+1...n]的和是array[j+1...k]的最大值。由于array[m+1...j]使得array[i...j]的和小于0。此时我们可以比较array[i...m]和array[j+1...n],如果array[i...m]的和大于array[j+1...n]则array[i...m]>array[p...q],否array[j+1...n]>array[p...q],无论谁大,我们都可以找到比array[p...q]和更大的子串,这与我们的假设矛盾,所以满足条件的array[p...q]不可能跨越两个子串。对于跨越更多子串的情况,由于各子串的和均为负值,所以同样可以证明存在和更大的非跨越子串的存在。对于单元素和最大的特例,该结论也适用。

    根据上述结论,我们就得到了Kadane算法的执行流程,从头到尾遍历目标数组,将数组分割为满足上述条件的子串,同时得到各子串的最大前缀和,然后比较各子串的最大前缀和,得到最终答案。我们以array={−2, 1, −3, 4, −1, 2, 1, −5, 4}为例,来简单说明一下算法步骤。通过遍历,可以将数组分割为如下3个子串(-2),(1,-3),(4,-1,2,1,-5,4),这里对于(-2)这样的情况,单独分为一组。各子串的最大前缀和为-2,1,6,所以目标串的最大子串和为6。

    南阳理工44就是一个一维的字串和:

     

    子串和

    时间限制:5000 ms  |  内存限制:65535 KB
    难度:3

     

    描述

    给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该子序列的和最大,其中,1<=x<=y<=n。

     输入

    第一行是一个整数N(N<=10)表示测试数据的组数)
    每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的一行里有n个整数I(-100=<I<=100),表示数列中的所有元素。(0<n<=1000000)
    输出
    对于每组测试数据输出和最大的连续子串的和。
    样例输入
    1
    5
    1 2 -1 3 -2
    
    样例输出
    5
    
    #include<stdio.h> 
    int main() 
    {   
        int i,j,n,m,sum,maxsum;   
        scanf("%d",&n);    
        while(n--)
        {         
            scanf("%d%d",&m,&j); 
            sum=maxsum=j; 
            for(i=1;i<m;i++) 
            { 
                scanf("%d",&j); 
                if(sum<0)    
                   sum=j; 
                else   
                   sum+=j;  
                if(maxsum<sum) maxsum=sum; 
            } 
            printf("%d\n",maxsum); 
        } 
        return 0; 
    }

    最大和

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:5
     
    描述

    给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵。 
    例子:
    0 -2 -7 0 
    9 2 -6 2 
    -4 1 -4 1 
    -1 8 0 -2 
    其最大子矩阵为:

    9 2 
    -4 1 
    -1 8 
    其元素总和为15。 

     
    输入
    第一行输入一个整数n(0<n<=100),表示有n组测试数据;
    每组测试数据:
    第一行有两个的整数r,c(0<r,c<=100),r、c分别代表矩阵的行和列;
    随后有r行,每行有c个整数;
    输出
    输出矩阵的最大子矩阵的元素之和。
    样例输入
    1
    4 4
    0 -2 -7 0 
    9 2 -6 2 
    -4 1 -4 1 
    -1 8 0 -2 
    
    样例输出
    15
    
    
    //我们已经知道一维数组的最值求法,现在我们可以把二位数组转化为一维数组
    //我们可以把二维数组按照行数进行压缩
    #include<stdio.h> 
    #include<string.h>
    int max(int n,int *a)//这是求一维数组的最大值
    {
        int i,sum,maxsum;
        sum=maxsum=-9999999;
        for(i=0;i<n;i++)
        {
            if(sum<0)  sum=a[i];
            else sum+=a[i];
            maxsum=maxsum>sum?maxsum:sum;
        }
        return maxsum;
    }        
    int main() 
    {   
        int i,j,n,m,sum,maxsum,t,a[110][110],b[110],p;   
        scanf("%d",&p);    
        while(p--)
        {      
            maxsum=-9999999;
            scanf("%d%d",&n,&m);
            for(i=0;i<n;i++)
                for(j=0;j<m;j++)
                    scanf("%d",&a[i][j]);
            for(i=0;i<n;i++)//行号从0到n
            {
                memset(b,0,sizeof(b));
                for(j=i;j<n;j++)//把从i到n行压缩成一行
                {
                    for(t=0;t<m;t++)
                        b[t]+=a[j][t];
                       sum=max(m,b);//求每行的最值
                        maxsum=maxsum>sum?maxsum:sum;//总得最值
                    }
            }
         printf("%d\n",maxsum); 
        }
        return 0; 
    }
    
    
    
    
    
    
    
  • 相关阅读:
    maven打包出错: Failed to clean project: Failed to delete
    Image.Save()发生“GDI+ 中发生一般性错误”
    Vue.js——60分钟快速入门
    PHP-输入变量
    ThinkPHP框架开发的应用的标准执行流程
    ThinkPHP 3.2.2 在 volist 多重循环嵌套中使用 if 判断标签
    ThinkPHP 数据库操作之数据表模型和基础模型 ( Model )
    Namespace declaration statement has to be the very first statement in the script
    ThinkPHP 学习笔记 ( 一 ) 项目部署:应用部署方式与模块分组部署方式
    ThinkPHP 3.2.3 简单后台模块开发(一)常用配置
  • 原文地址:https://www.cnblogs.com/xiaofanke/p/2654652.html
Copyright © 2020-2023  润新知