1. 程式人生 > >最大子陣列問題(動態規劃)--【演算法導論】

最大子陣列問題(動態規劃)--【演算法導論】

前些天學車...真是相當累啊,比上課累,現在終於可以休息了...

重新看《演算法導論》,不過這下可得認真看了,9個月不到就得去找工作了,與我同樣的大三黨們一樣加油咯...

《演算法導論》中引入這個問題是通過股票的購買與出售,將前一天的當天的股票差價重新表示出來,即轉為了一個最大子陣列的問題,具體內容我不多說,轉的內容是:

13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7

找到這連續的16個數裡面的連續和最大的子陣列;

書中練習部分說用設計非遞迴的,線性時間的演算法,我就YY為動態規劃處理了;

從陣列的左邊界開始,從左至右處理,記錄到目前為止已經處理過的最大子陣列。若已知A[1..j]的最大子陣列,基於如下性質將解擴充套件為A[1...j+1]的最大子陣列:A[1...j+1]的最大子陣列要麼是A[1...j]的最大子陣列,要麼是某個子陣列A[i...j+1](1<=i<=j+1)。在已知A[1...j]的最大子陣列的情況下,可以線上性時間內找出形如A[i...j+1]的最大子陣列;

思想上述都將出來了,只要將關鍵點寫出即可:

如果前面若干和<0,則其對後面子陣列相加無幫助,此時重置dparray[i],並且記錄的起始位置重新標記;

        if(dp[i - 1] <= 0)  //前面的<0,直接丟棄
        {
            dp[i] = array[i];
            temp = i; //記錄起始為止
        }

否則,繼續往後延伸;

dp[i] = array[i] + dp[i - 1];  //往後求和

最後判斷最大子陣列值就行,同時標記起始與結束位置

        if(dp[i] > MaxSumSub)  //找到到i為止的最大子陣列
        {
            MaxSumSub = dp[i];  //最大...
            start = temp;  //標記起始
            end = i;  //標記此時的結束位置
        }


程式碼:

#include <iostream>

using namespace std;

int FindMaxSubarray(int array[], int length)
{
    int start = 0, end = 0;  //記錄最大子陣列的起始位置(在陣列中的下標)
    int MaxSumSub;  //最大子陣列的值
    int* dp = new int[length];  //動態規劃記錄

    dp[0] = array[0];  //初始為第一個數
    MaxSumSub = dp[0];  //最大值初始為第一個數
    int temp = 0;  //

    for(int i = 1; i < length; i++)
    {
        if(dp[i - 1] <= 0)  //前面的<0,直接丟棄
        {
            dp[i] = array[i];
            temp = i; //記錄起始為止
        }
        else
            dp[i] = array[i] + dp[i - 1];  //往後求和

        if(dp[i] > MaxSumSub)  //找到到i為止的最大子陣列
        {
            MaxSumSub = dp[i];  //最大...
            start = temp;  //標記起始
            end = i;  //標記此時的結束位置
        }
    }

    cout<<"最大子序列的下標:"<<start<<"->"<<end<<endl;
    return MaxSumSub;

}

int main()
{
    int a[] = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
    //int a[] = {23, 4};
    int length = sizeof(a) / sizeof(int);

    cout<<FindMaxSubarray(a, length);
    return 0;
}

最大子序列即為{18, 20, -7, 12};

上述dp即為動態記錄尋找最大子陣列的過程,大家也可以進行輸出看一下;

歡迎大家指點,o(∩_∩)o