動態規劃階段性學習總結

          這幾天相當煎熬,動態規劃實在是太難了,感覺最難的就是抽象遞歸,和貪心stl不同,dp代碼的關鍵位置是看不懂的,看十幾遍也整不動,以前最起碼可以根據代碼理清思路,現在只有將代碼實現過程寫到紙上手動跑才能勉強搞懂。
          一個最長上升子段和問題,整整一天,在紙上寫了一遍又一遍才把遞歸過程搞懂,現在說一下具體過程。
          問題不再贅述,直接舉例,給一個數列如下
                      1   7   2   8   3   4  
那麼它的最長上升子序列就是
                      1   2   3   4 
長度爲4,所以這個數列的最長子序列長度就是4。
         現在來展示最核心的遞歸過程(圖片出自知乎Mingqi)


         這裏我們可以看到,LIS(K+1)要麼等於LIS(K),要麼加了一。其實也很好理解,基本上就是,在前面所有的LIS種找到一個最長的LIS(i),如果A(K)比這個找到LIS(i)的尾項A(i)要大,則LIS(K)=LIS(i)+1,否則LIS(K)=LIS(i)。
           代碼實現如下
#include <iostream>
using namespace std;
int a[10001],maxlen[10001];
int main()
{
    int n;
    cin>>n;
    for(int i = 1;i<=n;i++)
        cin>>a[i];
    maxlen[1] = 1;
    for(int i = 2;i<=n;i++)
    {
        int temp = 0;//記錄最長子序列的最後一個元素
        for(int j = 1;j<i;j++)
        //遍歷i之前的所有元素,如果i大於j,那麼子序列累加
        {
            if(a[i]>a[j])
            {
                if(maxlen[j]>temp)
                    temp = maxlen[j];
            }
        }
        maxlen[i] = temp+1;
        //加1是包含a[i]本身
    }
    int amax = -1;
    for(int i = 1;i<=n;i++)
        amax = max(amax,maxlen[i]);
    cout<<amax<<endl;
    return 0;
}
        由這道題可以看出,dp最關鍵的就是遞歸的形式,也就是狀態轉移,一旦搞懂,豁然開朗!
        即使越學越絕望也不能放棄,就要和dp肝到底,一天整不懂就兩天,一道題不行就兩道三道,積累量變,總能質變。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章