题目
题目大意
给定一组整数序列,求该序列中连续子序列的最大和,如果有多个子序列,取i和j较小的,输出值以及ij对应的值。
思路
刚开始把整个序列累加,用双指针,求右指针-左指针的最大值。但是第1个测试点过不去,24分。后来参考别人的代码,还有一种方法是动态规划。不用累加,直接看当前和temp是否大于0,如果小于0,说明在整个序列中起副作用,可以直接舍去;如果大于0,看是否大于sum,如果大于sum就更新sum值以及左右指针的索引。
代码1
测试点1不能过
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int k;
cin >> k;
vector<int> v(k + 1);
int flag = 0; // 是否全为负数
int flag2 = 0; // 是否存在正数
v[0] = 0;
for (int i = 1; i <= k; i++){
cin >> v[i];
if (v[i] >= 0) flag = 1;
if (v[i] > 0) flag2 = 1;
v[i] += v[i - 1];
}
int maxn = 0, q = v[1], h = v[k] - v[k - 1]; // 初始化
for (int i = 0, j = i + 1; j <= k;){
if (v[j] >= v[j - 1]){
j++;
if (maxn < v[j - 1] - v[i]){
maxn = v[j - 1] - v[i];
q = v[i + 1] - v[i];
h = v[j - 1] - v[j - 2];
}
}else{
if (maxn < v[j - 1] - v[i]){
maxn = v[j - 1] - v[i];
q = v[i + 1] - v[i];
h = v[j - 1] - v[j - 2];
}
i = j;
j = i + 1;
}
}
if (flag == 1 && flag2 == 0){ // 只有负数和0(测试点5)
cout << "0 0 0" << endl;
}else if (flag == 0){
cout << "0 " << v[1] << " " << v[k] - v[k - 1] << endl;
}else{
cout << maxn << " " << q << " " << h << endl;
}
return 0;
}
代码2
可以通过
#include <iostream>
#include <vector>
using namespace std;
int main(){
int k;
cin >> k;
vector<int> v(k);
int sum = -1, l = 0, r = k - 1, temp = 0, t = 0;
for (int i = 0; i < k; i++){
cin >> v[i];
temp += v[i];
if (temp < 0){
temp = 0;
t = i + 1;
}else if (temp > sum){
sum = temp;
l = t;
r = i;
}
}
if (sum < 0) sum = 0;
cout << sum << " " << v[l] << " " << v[r] << endl;
return 0;
}