51Nod-1050 循环数组最大子段和
基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题
N个整数组成的循环序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑a[n-1],a[n],a[1],a[2]这样的序列)。当所给的整数均为负数时和为0。
例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
Input
第1行:整数序列的长度N(2 <= N <= 50000) 第2 - N+1行:N个整数 (-10^9 <= S[i] <= 10^9)
Output
输出循环数组的最大子段和。
Input示例
6 -2 11 -4 13 -5 -2
Output示例
20
题意就不说了大家都理解。
最长子序列题(可循环)。
有两种情况:一:是这个最长子序列长度在1-N之间。那么就和之前的最长子序列一样的写法。
二:这个最长子序列不在1-N之间,而是在循环的之间。那么此时在1-N之间的非最长子序列段和的负的最多(绝对值最大)。
下面是代码:
1 #include<stdio.h> 2 int T; 3 long long a[50010]; 4 long long max(long long a,long long b) 5 { 6 if(a>b) return a; 7 return b; 8 } 9 long long SUM(long long a[]) 10 { 11 long long sum=0; 12 long long max1=0; 13 for (int i=0;i<T;i++) 14 { 15 if(sum<0) sum=a[i]; 16 else sum+=a[i]; 17 if(sum>max1) max1=sum; 18 } 19 return max1; 20 } 21 int main() 22 { 23 scanf("%d",&T); 24 long long sum=0; 25 long long ans; 26 long long ans2; 27 for (int i=0;i<T;i++) 28 { 29 scanf("%lld",&a[i]); 30 sum+=a[i]; 31 } 32 ans=SUM(a); 33 for (int i=0;i<T;i++) 34 a[i]=-a[i]; 35 ans2=SUM(a); 36 sum=max(ans,sum+ans2); 37 printf("%lld\n",sum); 38 return 0; 39 }
用DP写:其实就改了一个地方= =
1 #include<stdio.h> 2 #include<string.h> 3 int T; 4 long long a[50010]; 5 long long DP[50010]; 6 long long max(long long a,long long b) 7 { 8 if(a>b) return a; 9 return b; 10 } 11 long long SUM(long long a[]) 12 { 13 long long max1=0; 14 for (int i=0;i<T;i++) 15 { 16 DP[i]=max(DP[i-1]+a[i],a[i]); 17 if(DP[i]>max1) max1=DP[i]; 18 } 19 return max1; 20 } 21 int main() 22 { 23 memset(DP,0,sizeof(DP)); 24 scanf("%d",&T); 25 long long sum=0; 26 long long ans; 27 long long ans2; 28 for (int i=0;i<T;i++) 29 { 30 scanf("%lld",&a[i]); 31 sum+=a[i]; 32 } 33 ans=SUM(a); 34 for (int i=0;i<T;i++) 35 a[i]=-a[i]; 36 ans2=SUM(a); 37 sum=max(ans,sum+ans2); 38 printf("%lld\n",sum); 39 return 0; 40 }