zoukankan      html  css  js  c++  java
  • 最大子段和、最大子矩阵和

    最大子段和

    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;
    }
  • 相关阅读:
    通用标签
    网页基础
    WCF---服务发布的步骤
    锁·——lock关键字详解
    C# 实现磁性窗体
    C#中的线程(三) 使用多线程
    C#中的线程(二) 线程同步基础
    C#中的线程(一)入门
    class A<T> where T:class 这个泛型类中的Where T:class什么意思
    OO真经——关于面向对象的哲学体系及科学体系的探讨(下)
  • 原文地址:https://www.cnblogs.com/Initial-C-/p/13719934.html
Copyright © 2011-2022 走看看