任务:使用枚举、分治及动态规划三种算法实现最大子段和问题。
任务描述:给定n个整数(可能为负数)组成的序列X,求该序列如x[i]+x[i+1]+…+x[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,x[i]+x[i+1]+…+x[j]},1<=i<=j<=n
输入:序列X
输出:最大子段和
//分治算法
#include<stdio.h>
int a[]={0,13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7,-9,4,8,1,4,-5,-2,1,-3,6,8,-18,9};
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 s1=0;
int lefts=0;
for(int i=center;i>=left;i--){
lefts +=a[i];
if(lefts>s1)
s1=lefts;
}
int s2=0;
int rights=0;
for(int i=center;i<=right;i++){
rights +=a[i];
if(rights>s2)
s2=rights;
}
sum=s1+s2;
if(sum<leftsum){
sum=leftsum;
}
if(sum<rightsum){
sum=rightsum;
}
}
return sum;
}
int MaxSum(int n,int*a){
return MaxSubSum(a,1,n);
}
//枚举算法
int MaxSum(int n,int*a,int& besti,int& bestj){
int sum=0;
for(int i=1;i<=n;i++){
int thissum=0;
for(int j=i;j<=n;j++){
thissum+=a[j];
if(thissum>sum){
sum=thissum;
besti=i;
bestj=j;
}
}
}
return sum;
}
//动态规划法
int MSum(int n,int *a){
int sum=0,b=0;
for(int i=1;i<=n;i++){
if(b>0){
b+=a[i];
}
else{
b=a[i];
}
if(b>sum){
sum=b;
}
}
return sum;
}
//主函数
int main(){
int besti=0,bestj=0;
printf("分治:\n sum=%d\n",MaxSubSum(a,0,30));
printf("besti=%d bestj=%d",besti,bestj);
printf("枚举:\n sum=%d\n",MaxSum(30,a,besti,bestj));
printf("动态规划:\n sum=%d",MSum(30,a));
return 0;
}