目录
最大字段和
任务:使用枚举、分治及动态规划三种算法实现最大子段和问题。
任务描述:给定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 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+1;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 maxsubsum(int n,int *a){
return maxsubsum(a,0,n-1);
}
int main(){
int a[] = {1,-3,7,8,-4};
for(int i= 0; i < 6; i++)
{
printf("%d ",a[i]);
}
int b=maxsubsum(6,a);
printf("\n");
printf("分治法数组a的最大连续子段和为:%d",b);
return 0;
}
枚举算法
#include<iostream>
using namespace std;
int maxSum(int n, int a[], int &besti, int &bestj){
int sum = 0;
for(int i= 0; 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 main(){
int a[] = {-2,11,-4,13,-5,-2,};
for(int i=0; i<6; i++)
{
cout<<a[i]<<" ";
}
int besti,bestj;
printf("\n");
printf("数组a的最大连续子段和为:%d",maxSum(6,a,besti,bestj));
return 0;
}
动态规划算法
#include<stdio.h>
int maxsubsum(int a[], int n){
int sum = 0;
int b = 0;
for(int i = 0; i < n; i++){
if(b > 0){
b += a[i];
}else{
b = a[i];
}
if(b > sum){
sum = b;
}
}
return sum;
}
int main(){
int a[] = {1,-3,7,8,-4};
for(int i= 0; i < 7; i++)
{
printf("%d ",a[i]);
}
int b=maxsubsum(a,6);
printf("\n");
printf("动态规划法数组a的最大连续子段和为:%d",b);
return 0;
}