题目描述:
Given a sequence of K integers { N 1 , N 2 , …, N K }. A continuous subsequence is defined to be { N i , N i+1 , …, N j} where 1≤i≤j≤K. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.
Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.
Input Specification:
Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (≤10000). The second line contains K numbers, separated by a space.
Output Specification:
For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.
Sample Input:
10
-10 1 2 3 4 -5 -23 3 7 -21
Sample Output:
10 1 4
题目大意:
给出一段无序的数,需要找出来哪一段连续的数和是最大的。输出最大的和,开始的位置,结束的位置。
代码如下:
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
int n,k=0,first,last,max1=-1;
cin>>n;
int a[n],b[n]={0};
for(int i=0;i<n;i++){
cin>>a[i];
if(a[i]>max1) max1=a[i];
}
b[k]=a[0];
for(int i=1;i<n;i++){
if(a[i]*b[k]>0) b[k]+=a[i];
else b[++k]+=a[i];
}
for(int i=0;i<=k-2;i++){
if((b[i]+b[i+2]>abs(b[i+1]))) b[i+1]+=b[i+2]+b[i];
}
sort(b,b+n);
if(max1<0) cout<<"0"<<" "<<a[0]<<" "<<a[n-1];
else {
for(int i=0;i<n;i++){
first=a[i];int sum=0;
for(int j=i;j<n;j++){
sum+=a[j];
if(sum==b[n-1]) {
cout<<b[n-1]<<" "<<first<<" "<<a[j];
exit(0);
}
}
}
}
return 0;
}
来总结一下:
1)用b数组来把这一段数压缩,压缩为一个正数一个负数的顺序,存储到数组b当中。写的时候感觉有点瞎猫碰上死耗子的感觉(只比较两个数的和是否大于他俩中间的数竟然可以AC)写的确实有点问题,但是竟然能AC。。。。。。
2)找开始的数和结束的数就是暴力列举,从头试到尾。
综合一下别人的思路:
来一个数就加一个数,如果加完之后的和为负数,就直接舍弃之前所有数的和。用leftnum来记录开始的下标位置,用rightnum来记录结束的下标位置,用tempnum来记录临时的开始位置的下标,如果temp的值比sum的值大的话,就直接替换sum。可能有这样的疑问,如果中间碰见一个特别小的是负数怎么办? 其实当你碰见这个负数的时候,除非前面全部是负数,要不然你此时前面的最大值,已经赋值给了sum,leftnum,rightnum(他们是有值的)。这个temp<0时的舍弃,确实很巧妙!
代码如下:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n;
cin>>n;
int sum=-1,temp=0,leftnum=0,rightnum=n-1,tempnum=0;
vector<int>v(n);
for(int i=0;i<n;i++){
scanf("%d",&v[i]);
temp+=v[i];
if(temp<0){
temp=0;
tempnum=i+1;
}
else if(temp>sum){
leftnum=tempnum;
rightnum=i;
sum=temp;
}
}
if(sum<0) sum=0;
cout<<sum<<" "<<v[leftnum]<<" "<<v[rightnum];
return 0;
}
本文探讨了寻找一组整数中具有最大和的连续子序列的算法,通过两种不同的实现方式,展示了如何有效地找到该子序列及其总和,同时考虑了特殊情况如全负数序列。
954

被折叠的 条评论
为什么被折叠?



