?? p07.muse
字號:
#title P07: 有依賴的背包問題* 簡化的問題這種背包問題的物品間存在某種“依賴”的關(guān)系。也就是說,i依賴于j,表示若選物品i,則必須選物品j。為了簡化起見,我們先設(shè)沒有某個物品既依賴于別的物品,又被別的物品所依賴;另外,沒有某件物品同時依賴多件物品。* 算法這個問題由NOIP2006金明的預(yù)算方案一題擴展而來。遵從該題的提法,將不依賴于別的物品的物品稱為“主件”,依賴于某主件的物品稱為“附件”。由這個問題的簡化條件可知所有的物品由若干主件和依賴于每個主件的一個附件集合組成。按照背包問題的一般思路,僅考慮一個主件和它的附件集合。可是,可用的策略非常多,包括:一個也不選,僅選擇主件,選擇主件后再選擇一個附件,選擇主件后再選擇兩個附件……無法用狀態(tài)轉(zhuǎn)移方程來表示如此多的策略。(事實上,設(shè)有n個附件,則策略有2^n+1個,為指數(shù)級。)考慮到所有這些策略都是互斥的(也就是說,你只能選擇一種策略),所以一個主件和它的附件集合實際上對應(yīng)于[[P06]]中的一個物品組,每個選擇了主件又選擇了若干個附件的策略對應(yīng)于這個物品組中的一個物品,其費用和價值都是這個策略中的物品的值的和。但僅僅是這一步轉(zhuǎn)化并不能給出一個好的算法,因為物品組中的物品還是像原問題的策略一樣多。再考慮[[P06]]中的一句話: *可以對每組中的物品應(yīng)用[[P02]]中“一個簡單有效的優(yōu)化”。* 這提示我們,對于一個物品組中的物品,所有費用相同的物品只留一個價值最大的,不影響結(jié)果。所以,我們可以對主件i的“附件集合”先進行一次01背包,得到費用依次為0..V-c[i]所有這些值時相應(yīng)的最大價值f'[0..V-c[i]]。那么這個主件及它的附件集合相當于V-c[i]+1個物品的物品組,其中費用為c[i]+k的物品的價值為f'[k]+w[i]。也就是說原來指數(shù)級的策略中有很多策略都是冗余的,通過一次01背包后,將主件i轉(zhuǎn)化為V-c[i]+1個物品的物品組,就可以直接應(yīng)用[[P06]]的算法解決問題了。* 較一般的問題更一般的問題是:依賴關(guān)系以圖論中“森林”的形式給出(森林即多叉樹的集合),也就是說,主件的附件仍然可以具有自己的附件集合,限制只是每個物品最多只依賴于一個物品(只有一個主件)且不出現(xiàn)循環(huán)依賴。解決這個問題仍然可以用將每個主件及其附件集合轉(zhuǎn)化為物品組的方式。唯一不同的是,由于附件可能還有附件,就不能將每個附件都看作一個一般的01背包中的物品了。若這個附件也有附件集合,則它必定要被先轉(zhuǎn)化為物品組,然后用分組的背包問題解出主件及其附件集合所對應(yīng)的附件組中各個費用的附件所對應(yīng)的價值。事實上,這是一種樹形DP,其特點是每個父節(jié)點都需要對它的各個兒子的屬性進行一次DP以求得自己的相關(guān)屬性。這已經(jīng)觸及到了“泛化物品”的思想。看完[[P08]]后,你會發(fā)現(xiàn)這個“依賴關(guān)系樹”每一個子樹都等價于一件泛化物品,求某節(jié)點為根的子樹對應(yīng)的泛化物品相當于求其所有兒子的對應(yīng)的泛化物品之和。* 小結(jié)NOIP2006的那道背包問題我做得很失敗,寫了上百行的代碼,卻一分未得。后來我通過思考發(fā)現(xiàn)通過引入“物品組”和“依賴”的概念可以加深對這題的理解,還可以解決它的推廣問題。用物品組的思想考慮那題中極其特殊的依賴關(guān)系:物品不能既作主件又作附件,每個主件最多有兩個附件,可以發(fā)現(xiàn)一個主件和它的兩個附件等價于一個由四個物品組成的物品組,這便揭示了問題的某種本質(zhì)。我想說:失敗不是什么丟人的事情,從失敗中全無收獲才是。[[Index][首頁]]--------Copyright (c) 2007 Tianyi CuiPermission is granted to copy, distribute and/or modify this document under the terms of the [[http://www.gnu.org/licenses/fdl.txt][GNU Free Documentation License]], Version 1.2 or any later version published by the Free Software Foundation.
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -