進擊的DP----數位DP入門到理解

今天是集訓的第一階段的結束。

第一階段 是以DP入門爲主。因爲智力真的有限,學長介紹了那麼多的DP實在有點接受不了,所有這幾天一直在搞數位DP。

先談一些我的理解,在我看來,數位dp就是一種優雅的暴力。

數位DP是一類計數問題。

具體題目大體以,統計一個區間【L,R】內,滿足條件的數有多少個。

數位dp特徵:一般L,R都會取1e9~1e18之間的數。

因爲只是入門,所以大體介紹一下。

在我看來,數位dp有三種解決方法。

一.DFS記憶化搜索

這應該是最常見的解決方法了,對狀態進行搜索。DFS搜索進行排除不合意的條件。

通常都會有模板。(偷自一位dalao的博客)

int dfs(int i, int s, bool e) {
    if (i==-1) return s==target_s;
    if (!e && ~f[i][s]) return f[i][s];
    int res = 0;
    int u = e?num[i]:9;
    for (int d = first?1:0; d <= u; ++d)
        res += dfs(i-1, new_s(s, d), e&&d==u);
    return e?res:f[i][s]=res;
}

其中:

f爲記憶化數組;

i爲當前處理串的第i位(權重表示法,也即後面剩下i+1位待填數);

s爲之前數字的狀態(如果要求後面的數滿足什麼狀態,也可以再記一個目標狀態t之類,for的時候枚舉下t);

e表示之前的數是否是上界的前綴(即後面的數能否任意填)。

for循環枚舉數字時,要注意是否能枚舉0,以及0對於狀態的影響,有的題目前導0和中間的0是等價的,但有的不是,對於後者可以在dfs時再加一個狀態變量z,表示前面是否全部是前導0,也可以看是否是首位,然後外面統計時候枚舉一下位數。It depends.

於是關鍵就在怎麼設計狀態。當然做多了之後狀態一眼就可以瞄出來。

博客地址:http://www.cnblogs.com/jffifa/archive/2012/08/17/2644847.html

二.預處理區間

先對所有的特徵片段區間進行篩查,排除不可能或者可能的情況,用數組保存

然後將n進行分解,利用for循環進行判斷,得出正確結論

三.強行DP數組暴力

來自我學長的代碼的啓示,利用幾層for循環進行暴力。。(只是對比前兩種方法得出的結論)




可能這麼說有點吃力也不好懂。。畢竟是一隻萌萌的菜雞。結合具體題目來寫吧

發佈了24 篇原創文章 · 獲贊 8 · 訪問量 3208
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章