2086 Problem A 最大連續子序列
問題 A: 最大連續子序列
時間限制: 1 Sec 記憶體限制: 32 MB
提交: 198 解決: 93
[提交][狀態][討論版][命題人:外部匯入]
題目描述
給定K個整數的序列{ N1, N2, ..., NK },其任意連續子序列可表示為{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K。最大連續子序列是所有連續子序列中元素和最大的一個,例如給定序列{ -2, 11, -4, 13, -5, -2 },其最大連續子序列為{ 11, -4, 13 },最大和為20。現在增加一個要求,即還需要輸出該子序列的第一個和最後一個元素。
輸入
測試輸入包含若干測試用例,每個測試用例佔2行,第1行給出正整數K( K<= 10000 ),第2行給出K個整數,中間用空格分隔,每個數的絕對值不超過100。當K為0時,輸入結束,該用例不被處理。
輸出
對每個測試用例,在1行裡輸出最大和、最大連續子序列的第一個和最後一個元素,中間用空格分隔。如果最大連續子序列不唯一,則輸出序號i和j最小的那個(如輸入樣例的第2、3組)。若所有K個元素都是負數,則定義其最大和為0,輸出整個序列的首尾元素。
樣例輸入
5 -3 9 -2 5 -4 3 -2 -3 -1 0
樣例輸出
12 9 5 0 -2 -1
提示
這是一道稍微有點難度的動態規劃題。
首先可以想到的做法是列舉每個區間的和,預處理sum[i]來表示區間[1, i]的和之後通過減法我們可以O(1)時間獲得區間[i, j]的和,因此這個做法的時間複雜度為O(n^2)。
然後這題的資料範圍較大,因此還需作進一步優化才可以AC。記第i個元素為a[i],定義dp[i]表示以下標i結尾的區間的最大和,那麼dp[i]的計算有2種選擇,一種是含有a[i-1],一種是不含有a[i-1],前者的最大值為dp[i-1]+a[i],後者的最大值為a[i]。而兩者取捨的區別在於dp[i-1]是否大於0。
#include<iostream> #include<algorithm> using namespace std; //這類簡單的實際上可不加陣列 int main() { int n; while (cin >> n&&n) { int a[10050], dp[10050]; bool flag = true; for (int i = 0; i < n; i++) { cin >> a[i]; if (a[i] > 0) flag = false; } if (flag) { cout << "0 " << a[0] << " " << a[n - 1] << endl; continue; } dp[0] = a[0]; for (int i = 1; i < n; i++) { dp[i] = max(a[i], dp[i - 1] + a[i]); } int index = 0, num = 0; for (int i = 1; i < n; i++) { if (dp[i] > dp[index]) index = i; } for (int i = index; i >= 0; i--) {//尋找首元素下標 num += a[i]; if (num == dp[index]) { num = i; break; } } cout << dp[index] << " " << a[num] << " " << a[index] << endl; } return 0; }