最近兩天為樹形背包問題所困擾。 這一切的起因是一年前在 hackerrank 上做的一道題 A Knapsack Problem。
題目大意是:
給一棵 $N$ 個節點的樹,節點 $i$ 代表一件價值為 $v[i]$,體積為 $s[i]$ 的物品。另有一個體積為 $M$ 的背包,要求在樹上選一個連通塊裝進背包,使得所選物品的總價值最大。
數據范圍:
$ N, M \le 2000 $
朴素的做法復雜度是 $O(NM^2)$,TLE。一直沒看editorial,拖到現在。做這題之前我已看過崔添翼的《背包九講》,期間又讀了2009年國家集訓隊徐持衡的論文《淺談幾類背包問題》,徐的論文中提到樹形依賴背包問題有 $O(NM)$ 解法,我很高興,然而看了以后並不能懂。最近又想起這道題,再去翻徐的論文,折騰了兩天,才發現:
- 徐的論文講的比較簡略,確實有點難懂
- 徐所討論的樹形依賴背包問題和 A Knapsack Problem 根本不是同一個問題
徐論文中所謂的樹形依賴背包問題指的是:
給一棵 $N$ 個節點的有根樹,樹的每個節點代表一件價值為 $v[i]$,體積為 $s[i]$ 的物品。另有一個體積為 $M$ 的背包,要求在樹上選一個包含根節點的連通塊裝進背包,使得所選物品的總價值最大。
然而明確了這一點以后,我一時還是搞不懂徐持衡對此問題給出的$O(NM)$的樹形DP解法。又花了些功夫才基本弄懂:
$dp[i][j]$ 表示選擇了節點 $i$ (及其所有祖先節點) (即根節點到 $i$ 的路徑——記作 $P_i$ ——上的所有節點),此外再在 $P_i$ 的左側和子樹 $i$ 中選擇總體積不超過 $j$ 的物品的最大價值。