1. 程式人生 > >DP之數位,概率,樹形總結

DP之數位,概率,樹形總結

DP小練終於搞定了,前前後後用了兩星期,這次練習,主要是練習數位,概率和樹形dp,其中不乏有些很好的思想。
首先,我們來看看數位dp。一般的,數位dp都用於統計區間,滿足一些性質的數的個數,格式都比較固定,究其本質,不外乎先查詢【0, r】區間滿足該性質的數的個數,然後再求出【0, l - 1】區間滿足該性質的數的個數,然後相減即可。
這裡給出一段我的模板
int digit[70];
ll dp[65][22][22];

ll dfs(int pos, int cnt4, int cnt7, int flag) {
    if(cnt4 > x || cnt7 > y) return
0; if(pos < 1) return (cnt4 == x && cnt7 == y); ll &ret = dp[pos][cnt4][cnt7]; if(!flag && ret != -1) return ret; int up = flag ? digit[pos] : 9; ll ans = 0; for(int i = 0; i <= up; i++) { ans += dfs(pos-1, cnt4 + (i == 4), cnt7 + (i == 7), flag && i == up); } if
(!flag) ret = ans; return ans; } ll cal(ll n) { int len = 0; while(n) { digit[++len] = n % 10; n /= 10; } return dfs(len, 0, 0, 1); }

有時候,數位dp會存在一些變形,例如HDU3943要求找到具體的滿足條件的區間內的最大值,這個我們利用二分搜尋,列舉答案,在上一次dp的基礎上,繼續做dp,不斷縮小解空間,找到最優解。
再例如HDU3709,我們需要列舉平衡位置,來進行dp然後查詢最優解否則無法統計。

概率dp獲益良多。
POJ3744,如果橫著掃一遍 統計過去,那麼時間開銷太大了,由資料,我們發現埋雷的位置很少,我們從這下功夫,然後在畫畫,可以發現,決策為f[n] = a * f[n-1] + b * f[n-2],其中a, b是常數。於是,列舉雷前面的位置,然後用矩陣快速冪加速顯然。
概率dp一般是順著來的(因為起點為1的話,他的概率就為1,往後順推容易計算)
期望dp一般是倒著來的(通常,把達到的目標狀態期望設定為0)
概率dp和期望dp並不是很難,但是當我們根據題設條件列出方程的時候,化簡是比較煩的,這時候需要的是細心和耐心。
再者,概率和期望想要學好,論文是必須要看的。
ZOJ3329是比較基礎的,容易推到方程。
當我們遇到類似於POJ2151這種題,我們需要順著+倒著想一次,然後才能利用條件概率的知識解出正確答 有時候,推匯出來的方程,往往依賴於之前未計算出來的狀態(多見於期望dp),我們可能需要迭代,或者分拆方程的方法,例如HDU4035,後面的值依賴於前面的節點,我們需要改變下原狀態方程,用數學代換,再迭代,解出輔助方程的轉移方法。

最後再談談樹形dp,
樹形dp有兩種思維方式,一種是點分治,也就是說,當我們計算一個點時候,我們只需要計算以這個點為根的子樹(這是理想情況下,藍兒多數時候,是需要考慮到父親甚至祖先節點的,這時候,我們長可以用陳啟峰一張一弛解題之道的思想,科學的縮小或者放大解空間,直戳題目要害,問題才能迎刃而解)。還有一種是邊分治,例如找樹的重心。
此部落格會根據以後對dp的理解持續更新。