求和最大的连续子序列,输出最大的和以及该子序列的开始值和结束值。如果所有数都 < 0,那么认为最大的和为 0 ,并且输出首尾元素
(一)暴力解法
#include<iostream>
#include<vector>
using namespace std;
int sub[10010];
void find_maxsub(int sub[],int k){
int max = -1,first,last;
int i,j,sum;
for(i=0;i<k;i++){
sum = 0;
for(j=i;j<k;j++){
sum += sub[j];
if(sum > max){
max = sum;
first = i;
last = j;
}
}
}
cout << max << " " << sub[first] << " " << sub[last];
}
int main(){
int k;
cin >> k;
int flag=0;
for(int i=0;i<k;i++){
cin >> sub[i];
if(sub[i] >= 0) flag = 1;
}
if(flag==0){
cout << 0 << " " << sub[0] << " " << sub[k-1];
return 0;
}
find_maxsub(sub,k);
}
(2)动态 dp
max 为要求的最大和,sum 为临时最大和,first 和 last 为所求的子序列的下标,index 标记 first 的临时下标
sum = sum + v[ i ],当 sum 比 max 大,就更新 max 的值、first 和 last 的值;当 sum < 0,那么后面不管来什么值,都舍弃 sum < 0 前面的内容,因为负数对于总和只可能拉低总和,不可能增加总和,直接舍去即可
舍弃后,直接令 sum = 0,并且同时更新 first 的临时值 index
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
scanf("%d", &n);
vector<int> v(n);
int first = 0, last = n-1, max = -1, sum = 0, index = 0;
for(int i=0;i<n;i++){
scanf("%d",&v[i]);
sum = sum + v[i];
if(sum < 0) {
sum = 0;
index = i + 1;
}
else if(sum > max){
max = sum;
first = index;
last = i;
}
}
if(max < 0) max = 0;
printf("%d %d %d",max, v[first], v[last]);
}