動態規劃算法的思想及實現

介紹

動態規劃(簡稱DP)是算法設計思想當中最難也是最有趣的部分了,動態規劃適用於有重疊子問題和最優子結構性質的問題,是一種在數學、計算機科學和經濟學中常常使用的,經過把原問題分解爲相對簡單的子問題的方式求解複雜問題的方法。使用動態規劃方法解題有較高的時間效率,關鍵在於它減小了不少沒必要要的計算和重複計算的部分javascript

它的思想就是把一個大的問題進行拆分,細分紅一個個小的子問題,且可以從這些小的子問題的解當中推導出原問題的解。同時還須要知足如下兩個重要性質才能進行動態規劃java

  • 最優子結構性: 既所拆分的子問題的解是最優解。算法

  • 子問題重疊性質: 既在求解的過程中,每次產生的子問題並不老是新問題,有些子問題會被重複計算屢次。動態規劃算法正是利用了這種子問題的重疊性質,對每個子問題只計算一次,而後將其計算結果保存在一個表格中,當再次須要計算已經計算過的子問題時,只是在表格中簡單地查看一下結果,從而得到較高的解題效率數組

舉個栗子

首先先引一道動態規劃的經典問題最長不降低子序列spa

它的定義是: 設有由n個不相同的整數組成的數列b[n],如有下標$i_1<i_2<···<i_L 且b[i_1]<b[i_2]<···<b[i_L]$$則稱存在一個長度爲L的不降低序列。設計

例如3d

13,7,9,16,38,24,37,18,44,19,21,22,63,15code

那麼就有13<16<38<44<63長度爲5的不降低子序列。
可是通過觀察實際上還有7<9<16<18<19<21<22<63長度爲8的不降低子序列,那麼是否還有更長的不降低子序列呢?請找出最長的不降低子序列blog

輸入格式ip

第一行爲n,表示n個數(n<=100000),第二行爲n個數的數值(數字之間用空格隔開且最後一個數字末尾不能留有空格)

輸出格式

一個整數,表示最長不降低子序列的長度。

輸入例子

4

1 3 1 2

輸出例子

2

思路

假如要求得某一段的最優,就要想更小段的最優怎麼求,再看看由最小段的最優可否擴大推廣到最大段的最優;

假設這麼一個表:

表一

第三行表示該序列元素的所能鏈接的最長不降低子序列的長度,由於自己長度爲1,因此初始值都爲1

第四行表示連接於哪一個序列元素造成最長不降低子序列

先從倒數第二項63算起,在它的後面僅有一項,所以僅做一次比較,由於63>15,因此從63出發,不做任何連接,長度仍是爲1。

再看倒數第三項22,在它的後面有2項,所以必需要在這2項當中找出比22大,長度又是最長的數值做爲連接,因爲只有22<63,因此修改22的長度爲2,即自身長度加上所連接數值的長度,並修改連接位置爲13,也就是63的下標。

再看倒數第四項21,在它的後面有3項,所以必需要在這3項當中找出比21大,長度又是最長的數值做爲連接(注意:是長度),很容易看出,數值22知足該條件,所以,修改21的長度爲3,並修改連接位置爲12,即22的序列下標。

依次類推,最後結果以下表:

表二

最終狀態的轉移方程式爲: $f(i) = max {f(j)} +1 (b_j<b_i 且 i<j)$.時間複雜度爲$O(n^2)$

代碼

process.stdin.setEncoding('utf8');

var arr = [];
var bool = 0;
var n = 0;
var longest = 1;
var a = [];
var dp = [];

process.stdin.on('readable', function() {
  var chunk = process.stdin.read();
  if (chunk !== null) {
      arr.push(chunk.trim())
  }

  if(bool>=2){
      n = arr[0];
      process.stdin.emit('end')
  }

  bool++

});


process.stdin.on('end', function() {

    a = arr.slice(1).join(" ").split(" ").map(function(index, elem) {
        return parseInt(index);
    })

    for(let i = 0;i<n;i++){
        dp[i] = 1;
    }

    for(let i = 1;i<n;i++){

        for(let j = 0;j<i;j++){
            if(a[i]>a[j]){
                dp[i] = Math.max(dp[j]+1,dp[i])
            }
            longest = Math.max(dp[i],longest)
        }

    }

    console.log("最長長度爲:"+longest);


      process.stdout.write('end');
});
相關文章
相關標籤/搜索