算法筆記---動態規劃:問題 A: 最大連續子序列

題目描述

給定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

解題思路:

使用動態規劃求解
dp[i] 表示以nums[i] 作爲結尾的最大子序列的和。

之前的題目只需要求出最大子序列的和即可。
如:劍指offer—連續子數組的最大和

該題較爲複雜,需要求解的問題比較多。

1、求出dp數組
2、求出最大子序列的起始下標和結尾下標
3、判斷當前序列是否都爲負數,若都爲負數,則直接輸出0 序列起始下標 序列結尾下標
4、若最大子序列不唯一,則輸出較小的子序列的下標。

下面爲AC代碼:

/*
 * @Description: 最大連續子序列和
 * @Author: 
 * @Date: 2020-05-02 15:10:22
 * @LastEditTime: 2020-05-02 15:38:53
 * @LastEditors: Please set LastEditors
 */
#include<iostream>
#include<algorithm>
using namespace std;

const int max_n = 10010;
int nums[max_n]; //存放序列的數組
int dp[max_n];//dp[i] 表示以nums[i] 作爲尾部的最大最子序列的和

int main(){
    int n;
    while(cin>>n){
        if(n == 0){
            break;
        }
        fill(nums,nums + max_n,0);
        for(int i = 0;i < n;i++){
            cin>>nums[i];
        }
        bool flag = false; //表示當前序列中都是負數
        for(int i = 0;i < n;i++){
            if(nums[i] > 0){
                flag = true;
                break;
            }
        }

        if(flag){
            fill(dp, dp + max_n, 0);
            dp[0] = nums[0];
            for (int i = 1; i < n; i++)
            {
                dp[i] = max(dp[i - 1] + nums[i], nums[i]);
            }
            int k = 0;//表示最大和下標
            for (int i = 0; i < n; i++)
            {
                if (dp[k] < dp[i])
                {
                    k = i;
                }
            }
            int j = k;//求出起始子序列的下標
            while (dp[j] - nums[j])
            {
                j--;
            }
            printf("%d %d %d\n", dp[k], nums[j], nums[k]);
        }else
        {
            //當前序列都是負數
            printf("%d %d %d\n",0,nums[0],nums[n - 1]);
        }   
    }
    system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章