zoukankan      html  css  js  c++  java
  • 分治法求最大子字段和

    View Code
    #include<iostream>
    using namespace std;
    int maxleft=0,maxright=0;//记录最大字段和起点和终点 
    int MaxSubsum(int *a,int left,int right){
        int sum=0;
        if(left==right) sum=a[left]>0?a[left]:0;
        else{
            
            int center=(left+right)/2;
            int leftsum=MaxSubsum(a,left,center);
            int rightsum=MaxSubsum(a,center+1,right);
            
            int i,j; 
            
            int s1=0;
            int lefts=0;
            for(i=center;i>=left;i--){//注意 :i的值是从center开始递减,不是从left开始递增 
                lefts+=a[i];
                if(lefts>s1) {          
                  s1=lefts;
                  maxleft=i;//记录最大字段和的最左边 
                }
            }
            
            int s2=0;
            int rights=0;
            for(j=center+1;j<=right;j++){
                rights+=a[j];
                if(rights>s2) {
                   s2=rights;
                   maxright=j;//记录最大字段和的最右边 
                }
            }
            
            sum=s1+s2;        
            if(sum<leftsum) {            
                sum=leftsum;
                if((right-left+1)%2==0)//如果最大字段和在左边,那么记录它的右边位置 
                   maxright=center;
                else
                   maxright=center-1;
            }
            if(sum<rightsum) {        
                sum=rightsum;
                maxleft=center+1;//如果最大字段和在右边,那么记录它的左边位置 
            }
        }
        
        return sum;
    }
    int main(){
        int n,a[100];
        cout<<"n:";
        cin>>n;
        a[0]=0;
        cout<<"请输入 "<<n<<" 元素:";
        for(int i=1;i<=n;i++)
            cin>>a[i];
        int max=MaxSubsum(a,1,n);
        cout<<"最大的和是"<<max<<endl; 
        cout<<"从第"<<maxleft<<"位置"<<"--> 第"<<maxright<<"位置相加"<<endl;
        
        int i;
        for(i=maxleft;i<maxright;i++)
            cout<<a[i]<<"+";
        cout<<a[i]<<"="<<max<<endl;
        return 0;
    }

     所给的序列a[1:n]的分为a[1:n/2]和a[n/1+1:n],分别求出这两段的最大字段和,则a[1:n]的最大字段和与三情形

    1.a[1:n]的最大字段和与a[1:n/2]的最大字段和相同

    2.a[1:n]的最大字段和a[n/2+1:n]的最大字段和相同

    3.a[1:n]的最大字段和为ai+..ak

    第三种情况可以看出a[n/2]和a[n/2+1]在最优子序列中,因此,可以在a[1:n/2]中计算出s1=max(a[i]+..+a[n/2]),并在a[n/2+1:n]中计算出s2=max(a[n/2+1]+..+a[j])

    s1+s2既为第三种情况的最优解

  • 相关阅读:
    不可重叠最长重复子串
    离散化
    hash是一门优雅的暴力
    Detect the Virus (字符串转化+AC自动机)
    病毒侵袭(AC自动机变形)
    hdu2069(Coin Change)
    Hie with the Pie(poj3311)
    poj3254(状压dp入门第一道题,很详细)
    map系统学习
    ACM-ICPC 2018 南京赛区网络预赛 B. The writing on the wall
  • 原文地址:https://www.cnblogs.com/aijianiula/p/2736326.html
Copyright © 2011-2022 走看看