zoukankan      html  css  js  c++  java
  • POJ2479,2593: 两段maximum-subarray问题

    虽然是两个水题,但是一次AC的感觉真心不错

    这个问题算是maximum-subarray问题的升级版,不过主要算法思想不变:

    1. maximum-subarray问题

    maximum-subarray就是找到数组A[1....n]中的连续子数组A[i.....j]并且A[i]+...+A[j]和最大。当然了,(1<=i<=j<=n)。

    maximum-subarray的O(n)解法就是从左到右扫描数组A,另外设置一工具数组DP,DP数组的作用就是记录以当前下标为终止下标的子数组和。比如DP[j]=A[i]+....+A[j](A[i] 到 A[j]是连续的)。现在假设我们已经求出DP[j],数组即将扫描A[j+1],则DP[j]与DP[j+1]的关系描述如下:

    DP[j+1]=(DP[j]>0)? (DP[j]+A[j+1]) : (A[j+1]).

    因为DP[j+1]要求出以j+1下标为结束下标的子数组和,而且DP[j]已经求出,所以我们要判断DP[j]是否为正数,如为正,则加上A[j+1]。如为负,那么很明显的,A[i]+.....+A[j]+A[j+1]<A[j+1], 所以要让DP[j+1]=A[j+1]。

    2. 求两个maximum-subarray问题

    这两个maximum-subarray不相交。

    我们可以设置一个“分水岭”,假设为k,那么maximum-subarray(A[1..k]) + maximum-subarray(A[k+1..n])就是我们要的解。

    当然如果我们枚举每一个k值(1<=k<=n-1)的话,因为题目开出的N值为50000,真个时间复杂度为O(n^2),必然超时。

    所以我们可以再设两个工具数组:lmax和rmax,lmax[i]表示A[1]到A[i]的最大子数组和,rmax[i]=A[i+1]....A[n]的最大子数组和。再次明确一下:lmax/rmax数组与DP数组的不同。

    假设DP[s]=A[p+..q+..+r+..s], 那么lmax[s]可能就等于A[q+...+r]或者A[p+...+r]或者等等。

    然后我们得到每个lmax[k]+rmax[k],对k进行枚举,lmax[k]+rmax[k]值最大的即为最后的解。

    附上POJ2593代码:(POJ2479改动一点就可以了)

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<map>
    #include<vector>
    using namespace std;
    const int max_size=100010;
    int n,a[max_size];
    int ldp[max_size],rdp[max_size],ans,inf=1<<30;
    int lmax[max_size],rmax[max_size];
    int main(){
        while(scanf("%d",&n)!=EOF&&n){
            memset(a,0,sizeof(a));
            memset(ldp,0,sizeof(ldp));
            memset(rdp,0,sizeof(rdp));
            memset(lmax,0,sizeof(lmax));
            memset(rmax,0,sizeof(rmax));
            ans=-inf;
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            } 
            lmax[1]=ldp[1]=a[1]; 
            for(int i=2;i<=n;i++){
                if(ldp[i-1]>0) ldp[i]=ldp[i-1]+a[i];
                else ldp[i]=a[i];
                ans=max(ans,ldp[i]);
                lmax[i]=ans;
            }
    
            rmax[n]=rdp[n]=a[n];
            ans=-inf;
            for(int i=n-1;i>=1;i--){
                if(rdp[i+1]>0) rdp[i]=rdp[i+1]+a[i];
                else rdp[i]=a[i];
                ans=max(ans,rdp[i]);
                rmax[i]=ans;
            }
            ans=-inf;
            for(int k=1;k<=n-1;k++){
                ans=max(ans,lmax[k]+rmax[k+1]);
            }
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    5 年,只为了一个更好的校验框架
    springboot 中 inputStream 神秘消失之谜
    没啥用的黑科技——自动生成测试对象信息框架
    投资中最简单的事
    一个提升英文单词拼写检测性能 1000 倍的算法?
    基于 junit5 实现 junitperf 源码分析
    关于 junit4 90% 的人都不知道的特性,详解 junitperf 的实现原理
    性能测试到底该怎么做?
    从代码生成说起,带你深入理解 mybatis generator 源码
    java 实现中英文拼写检查和错误纠正?可我只会写 CRUD 啊!
  • 原文地址:https://www.cnblogs.com/fu11211129/p/4214994.html
Copyright © 2011-2022 走看看