這是最大子序列和問題,是一個典型的動態規劃題目,我在博客中對幾個常見的動態規劃算法進行了分析。設輸入的數保存在數組a[max]
中,那麼轉移方程爲dp[i]=max(dp[i-1]+a[i],a[i])
。最大子序列和即爲dp數組的最大值res,我們記錄下zp數組第一次出現最大值的位置last,從last往前將a[i]數組的值加起來,直到值爲res爲止,此時的位置就是最大子序列的起始位置first。需注意題目規定當輸入的數全爲負數時輸出0和首位、末尾的數,這點需要提前特判。
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 1e4+10;
int a[maxn], dp[maxn];
int main(int argc, char const *argv[])
{
int K; scanf("%d", &K);
for(int i = 1; i <= K; i++) scanf("%d", &a[i]);
// 特判:若輸入的數全部小於0,則輸出0和首位、末尾的數
bool flag = true;
for (int i = 1; i <= K; ++i){
if(a[i]>=0) flag=false;
}
if(flag){
printf("%d %d %d\n", 0, a[1], a[K]);
return 0;
}
// 開始dp
dp[1] = a[1];
int res = dp[1];
for(int i = 2; i <= K; i++){
dp[i] = max(dp[i-1]+a[i], a[i]);
res = max(res, dp[i]);
}
int first, last; // 記錄首位和末位
for(int i = 1; i <= K; i++){
if(dp[i]==res) {
last=i;
break;
}
}
int temp = 0;
for(int i = last; i >= 1; i--){
temp += a[i];
if(temp==res) {
first=i;
break;
}
}
printf("%d %d %d\n", res, a[first], a[last]);
return 0;
}