1. 程式人生 > 其它 >程式碼源動態規劃學習

程式碼源動態規劃學習

樹形DP

樹上揹包

樹上揹包1:
給定一個n(<=2000)個點的樹,每個點有一個權值,權值可能是負數,選擇一個大小恰好為m的並且包含根節點的連通
塊,使得權值和最大
時間複雜度:O(n^2)
兩個揹包的大小分別是sa和sb,那麼合併這兩個揹包的代價大概是sa*sb級別的,也就是兩個揹包之間的每一對元素都有1
的貢獻,並且可以發現的是這一對元素只有在他的最近公共祖先合併兒子揹包的時候被計算一次,所以總的時間複雜度是
O(n^2)
樹上揹包2
給你一個n(1<=n<=50000)個節點的有根樹,每個點都有一個權值,要求選擇一個大小恰好為m(1<=m<=100)的連通塊的
最大權值
時間複雜度:O(nm)
因為每個節點他的權重只是1,所以他的組合情況就比較少,當我們使用以下程式碼實現的時候複雜度就不會很高,例如四個
節點,他的狀態只能構成0,1,2,3,4幾個,但是當權重比較分散的時候,例如是1,2,4,8,雖然我們只有四個節點,但是他們能組成的狀態確實0-15,這樣的話複雜度就會退化成O(nm^2)

給你一個n(1<=n<=1000)個點的有根樹,每個點有一個重量w和權值v,要求你選一個重量恰好為m的包含根的連通塊
總結:
1. 如果合併兩個子樹的大小等於樹的大小的乘積的話,那麼複雜度就是O(n^2)的
2. 如果合併兩個子樹的代價等於子樹大小和m取min的乘積的話,複雜度就是O(nm)的
3. 如果不是這樣,就沒有相應的結論,比如合併的代價是O((su + sv)^2)
4. 如果是距離相關的話,因為距離不會超過子樹的大小,所以有類似的結論
練習1:在樹上找一個連通塊,滿足任意兩點之間的距離都不超過d,使得權值之和最大,權值可能是負數
f[i][j]:表示i這個子樹裡面,選擇一個包括i的連通塊,並且這個聯通塊中距離i這個點最遠距離是j
那麼合併子樹的聯通塊的時候,對於f[u][j1],f[v][j2]兩個子樹,他們需要滿足j1+j2+2<=d並且將結果更新到f[u]
[max(j1, j2)+1]裡面去
練習2:在樹上找一個點集,滿足任意兩點之間的距不小於d,使得權值之和最大,權值可能是負數
f[i][j]:表示在i個子樹裡面選一個包含i的點集,並且這個點集裡面距離i的最小距離是j,
那麼合併子樹的時候,