zoukankan      html  css  js  c++  java
  • 算法导论学习-子数组最大和问题

     一种算法是分治法:O(nlgn)

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 using namespace std;
     5 const int maxsize=1000001;
     6 int a[maxsize],sum[maxsize],n,inf=(1<<30);
     7 int b[maxsize];
     8 struct solution{
     9     int lpos,rpos,sum;
    10 };
    11 solution find_crossing_subarray(int low,int mid,int high){
    12     int left_sum=-inf,right_sum=-inf;
    13     int sum=0,max_left,max_right;
    14     for(int i=mid;i>=low;i--){
    15         sum+=a[i];
    16         if(sum>left_sum){
    17             left_sum=sum;
    18             max_left=i;
    19         }
    20     }
    21     sum=0;
    22     for(int i=mid+1;i<=high;i++){
    23         sum+=a[i];
    24         if(sum>right_sum){
    25             right_sum=sum;
    26             max_right=i;
    27         }
    28     }
    29     solution a;
    30     a.lpos=max_left;
    31     a.rpos=max_right;
    32     a.sum=left_sum+right_sum;
    33     return a;
    34 }
    35 solution find_maximum_subarray(int low,int high){    
    36     if(low==high){
    37         solution s;
    38         s.lpos=s.rpos=low;
    39         s.sum=a[low];
    40         return s;
    41     }
    42     int mid=(low+high)/2;
    43     solution left=find_maximum_subarray(low,mid);
    44     solution right=find_maximum_subarray(mid+1,high);
    45     solution middle=find_crossing_subarray(low,mid,high);
    46     if(left.sum>=right.sum&&left.sum>=middle.sum) return left;
    47     else if(middle.sum>=left.sum&&middle.sum>=right.sum) return middle;
    48     else return right;
    49 }
    50 int main(){
    51     while(scanf("%d",&n)!=EOF&&n){
    52         for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    53         for(int i=1;i<=n;i++){
    54             a[i]=b[n-i+1];
    55         }
    56         solution ans=find_maximum_subarray(1,n);
    57         printf("%d %d %d
    ",ans.sum,n-ans.rpos,n-ans.lpos);
    58     }
    59 }
    View Code

    另外一种是DP法,O(n)

    maxisum-subarray problem, in fact, is try to find subarray A[i...j] of array A[1..i...j..n](1<=i<=j<=n). And the problem is meaningful only when array A has both the positve value and negative elements.

    considering the size of problem:
    * if n==1, the problem is quite easy. A[1] is the right answer. 
    * if array A has more than one value, then we can use DP method to solve it. 

    considering the procedure has already checked the A[i-1], and is going to enter the i th check. then we can assume that we have already get the maximum subarray of the A[1...i-1]. Supposing the maxisum subarray of A[1..i-1] is A[p..i-1].

    Then, our procedure is going to the ith check, because we have aleady get the solution of A[1..i-1], and we will move to check A[i]. So how the relationship between sum[i-1] and sum[i]? (sum[i] stores the sum of subarray that end in A[i]). From our experience:

     

    * if sum[i-1]<0, then whatever the A[i] is, the sum of subarray A[p...i-1,i] must be smaller than that of subarray A[p..i-1]. so we modify the starting indice of maxisum array from 'p' to 'i'. And at the same time, we can know that the maxisum subarray of A[1...i] is notthe A[p...i] but the A[p...i-1]. so the value of maxisum remains the same: the sum of A[p...i].
    * For another circumstance, if sum[i-1]>0, we can take two situations into consideration, if A[i]>0 too, obviously, we should let sum[i]=sum[i-1]+a[i]. then for A[i]<0? in fact, we also need to plus A[i] onto sum[i-1]. as we know, in the (i-1)th calculation, acoording to the above assumption, we have already found the solution to the maxisum subarray: A[p...i-1]. So although the sum of A[p...i-1] is higher than that of A[p...i], in fact, in each iteration, we compare the value of sum[i-1] and sum[i] to the maxinum and store the maxinum. So we let the sum[i-1]+A[i] has no matter to the maxinum. 

     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 const int maxsize=101;
     5 int a[maxsize],sum[maxsize],n,inf=(1<<30);
     6 void solve(){
     7     if(n==0) return;
     8     int ans=-inf;
     9     sum[1]=a[1];
    10     int left=1,right=1;
    11     for(int i=2;i<=n;i++){
    12         if(sum[i-1]>0){
    13             sum[i]=sum[i-1]+a[i];
    14             right++;    
    15         }
    16         else{
    17             sum[i]=a[i];
    18             left=i;
    19         }
    20         if(sum[i]>ans) ans=sum[i];
    21     }
    22     printf("Subarray from indice %d->%d has the maximum sum: %d
    ",left,right,ans);        
    23 }
    24 int main(){
    25     while(scanf("%d",&n)!=EOF){
    26         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    27         solve();
    28     }
    29     return 0;
    30 }
    View Code
  • 相关阅读:
    Avizo
    NEWS
    HOWTO
    InstallShield 2012 Spring优惠升级到最新版本(2015.4.30之前)
    Windows系统补丁KB2962872导致InstallShield无法启动(解决方案已更新)
    HOWTO: InstallScript MSI工程取Log
    安装软件列表
    阿里云推荐码 hut29f
    ios 缺少合规证明
    ios开发错误之: Undefined symbols for architecture x86_64
  • 原文地址:https://www.cnblogs.com/fu11211129/p/4204951.html
Copyright © 2011-2022 走看看