求数列的最大字段和

来源:互联网 发布:无网络监控 编辑:程序博客网 时间:2024/05/19 04:05

求数列的最大字段和{0,1,-1,3,-4,5,6,7,-8,88}。

问题分析:

用二分法将实例中的数据分解为{0,1,-1,3,-4},{5,6,7,-8,88},第一个子问题的解是3,第二个子问题的解是88,两个子问题的解不能简单的得到原问题的解。由此看出此问题不能用二分法分解成为独立的两个子问题,子问题中间还有公共的子问题,这类问题称为子问题重叠问题。下面仍用二分法解决这类问题中的一些简单问题,处理不独立的子问题。

算法设计:如果将所给的序列a[1:n]分为长度相等的两段a[1:(n/2)]和a[(n/2)+1:n]分别为求出这两段的最大子段和,则a[1:n]的最大子段和有3中情形:

情形(1)   a[1:n]的最大子段和与a[1:(n/2)]的最大子段和相同。

情形(2)   a[1:n]的最大子段和与a[(n/2)+1:n]的最大子段和相同。

情形(3)   a[1:n]的最大子段和为a[i:j)],且1≤i≤(n/2), (n/2)+1≤j≤n。

程序代码:

#include<stdio.h>

int max_sub_sum(int a[], int left, int right);

int max_sum3(int a[],int n);

void main() 

{   int aa[]={0,1,-1,3,-4,5,6,7,-8,88};

    int bb=0;

    bb=max_sum3(aa,9);

    printf("最大子段和:%d\n",bb);

}

int max_sub_sum(int a[], int left, int right)

{      int center,i,left_sum,right_sum,s1,s2,lefts,rights;

if (left==right)

        if (a[left]>0)   return(a[left]) ;  

        else   return(0);

else

{      center=(left+right)/2;

left_sum=max_sub_sum(a,left,center);

right_sum=max_sub_sum(a,center+1,right);

s1=0;                                   /*处理情形3*/

lefts=0;

for (i=center;i>=left;i--)             

{    lefts=lefts+a[i]; 

     if( lefts>s1)  s1=lefts; }

s2=0;     rights=0;

for( i=center+1;i<= right;i++)

{    rights=rights+a[i];

if ( rights>s2)  s2=rights; }

if ((s1+s2)<left_sum&&right_sum<left_sum)  return(left_sum);

if ((s1+s2)<right_sum)    return(right_sum);  

return(s1+s2);    }     }

int max_sum3(int a[],int n)

{    return(max_sub_sum(a,1,n));   }

运行结果: 最大子段和为:98

原创粉丝点击