• 最大子段和、最大子矩阵和


    最大子段和

    Description

    给出n个整数序列(可能为负数)组成的序列a1a2, ..., an,求该序列形如的子段和的最大值。当所有整数均为负数时,定义最大子段和为0。

    Input

    多测试用例。每个测试用例占2行:

    第一行是序列的个数n(0 < n ≤ 10000),第二行是n个整数。

    Output

    为每个测试用例输出一行结果:最大子段和。

    Sample Input

    6
    -2 11 -4 13 -5 -2
    3
    1 2 3

    Sample Output

    20
    6

    问题分析

    很经典的dp问题,用dp[i]表示前i个数的最大子段和

    每次选择第i个数的时候判断前i-1个数的最大子段和是否为负,为负则舍去,为正就加上

    状态转移方程 dp[i]=max(dp[i-1],0)+dp[i]

    记录dp[i]的最大值

    代码实现

    #include<iostream>
    #include<cstring>
    using namespace std;
    #define MAX_DATA 10000
    #define INF 0x3f3f3f3f
    int a[MAX_DATA];
    int dp[MAX_DATA];
    int main()
    {
        int n;
        while(cin>>n){
            for(int i=1;i<=n;++i){
                cin>>a[i];
            }
            memset(dp,0,sizeof(dp));//初始化
            int ans=-INF;
            for(int i=1;i<=n;++i){
                dp[i]=max(dp[i-1],0)+a[i];
                ans=max(ans,dp[i]);//记录最大值
            }
            cout<<ans<<endl;
        }
        return 0;
    }

    最大子矩阵和

    Description

    给出一个m×n的矩阵,请输出它的最大子矩阵和。

    Input

    多测试用例,每个测试用例:

    第一行是两个正整数m和n,表示该矩阵的行数和列数。1 < m, n < 400

    接下来m行,每行n个整数,空格分隔。

    Output

    每个测试用例输出一行:该矩阵的最大子矩阵和。运算结果在int范围内。

    Sample Input

    4 4
    0 -2 -7 0
    9 2 -6 2
    -4 1 -4 1
    -1 8 0 -2

    Sample Output

    15

    问题分析

    用一个二维数组存储每列的前缀和,即a[i][j]表示第j列前i行的和

    之后就可以转换为一维的最大子段和问题

    代码实现

    #include<iostream>
    #include<cstring>
    using namespace std;
    #define MAX_DATA 400
    #define INF 0x3f3f3f3f
    int a[MAX_DATA+2][MAX_DATA+2];
    int dp[MAX_DATA+2][MAX_DATA+2];
    int main()
    {
        int m,n,x;
        while(cin>>m>>n){
            memset(a,0,sizeof(a));
            for(int i=1;i<=m;++i){
                for(int j=1;j<=n;++j){
                    cin>>x;
                    a[i][j]=a[i-1][j]+x;//存储每列前i行的和
                }
            }
            memset(dp,0,sizeof(dp));//初始化
            int ans=-INF;
            for(int i=1;i<=m;++i){
                for(int k=0;k<i;++k){//遍历第k行到第i行
                    for(int j=1;j<=n;++j){
                        dp[i][j]=max(dp[i][j-1],0)+a[i][j]-a[k][j];//最大子段和表示第k行到第i行的最大子矩阵
                        ans=max(ans,dp[i][j]);
                    }
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Maximum execution time of 30 seconds exceeded解决错误方法
    php 获取随机数的几个方式
    php header utf8 插入header("Content-type: text/html; charset=utf-8");
    php mysqli query 查询数据库后读取内容的方法
    win7 xampp 验证码,session出不来的问题
    apache 中 ServerAlias让多个域名绑定到同一空间
    最近很火的一条成长公式,看看你属于那一条!
    用crontab执行shell把top命令按日期追加到文件
    php CI 实战教程第一季百度经验杂志
    php 截取字符串第一个字符,截取掉字符串最后一个字符的方法
  • 原文地址:https://www.cnblogs.com/Initial-C-/p/13719934.html
Copyright © 2020-2023  润新知