在解決這個問題之前,我們先把揹包的相關問題的解決過一遍。
對於01揹包(每件物品只能用0或1次):
for(int i=1;i<=n;i++)
for(int j=v;j-w[i]>=0;j--)
dp[j]=max(dp[j],dp[j-w[i]]+c[i]);
對於完全揹包(每件物品使用數目不限):
for(int i=1;i<=n;i++)
for(int j=w[i];j<=v;j++)
dp[j]=max(dp[j],dp[j-w[i]]+c[i]);
對於分組揹包:(分組每一組裡選最優,加起來值最大)
for(int i=1;i<=n;i++)
for(int j=v;j>=0;j--)
for(int k=1;k<=count[i];k++) // 第 i 組內 第 k 件物品
if(j-w[i][k]>=0)
dp[j]=max(dp[j],dp[j-w[i][k]]+c[i][k]);
以上相關問題有一些題目,例如洛谷的p1048 採藥,p1060 開心的金明,p1049 裝箱問題等
說完了揹包,我們來考慮這道題。首先這道題樣例其實有歧義,第m行的主件m就是它的編號。我們可以把它看成完全揹包問題。對於每乙個主件來說都有四種情況:只要主件,主件+附件1,主件+附件2,主件+附件1+附件2。利用二維count陣列存下第i件主件第k種情況的價值。count[i][0]表示其主附件總個數,1代表主件,2,3,4,同上文。最後轉化為完全揹包問題解決即可。
#include#includeusing namespace std;
int n,m;
int w[130][5]; //容量
int count[130][5]; //價值
int dp[30010];
bool b[30010]; //判斷主附件
int t=1;
int main()
for(int i=1;i<=m;i++)
else
}for(int i=1;i<=m;i++)
}} for(int i=1;i<=m;i++)
}} for(int i=1;i<=m;i++)}}
} }cout
}
題解 P1064 金明的預算方案
樹形依賴揹包問題 每個點有個權值和體積,如果選了某個點那麼它的父親也必須選,問體積和 m的最大權值和。腫麼辦?我們考慮求出樹的後序遍歷,那麼對於i這棵子樹,它在後序遍歷上是連續一段,並且i在最後,這樣就可以確保轉移時需要的狀態已經計算完畢。考慮i選還是不選,如果選的話f i 可以從f i 1 轉移過...
P1064 金明的預算方案
原題鏈結 本來是道dp題,我們拿來練搜尋了 雖然最後還是寫了dp 一開始的時候把每個情況都單獨拿出來了變成01揹包 但是有可能出現 選了主件a 選了主件a和附件a1 同時被選中的情況 這樣當然就不符合題意了呀 因為每個主件頂多只有兩個附件所以可以列舉情況直接變成分組揹包 每組裡面只能選乙個 incl...
P1064 金明的預算方案
金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間金明自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說 你的房間需要購買哪些物品,怎麼布置,你說了算,只要不超過n元錢就行 今天一早,金明就開始做預算了,他把想買的物品分為兩類 主件與附件,附件是從屬於某個主件的,下表就是一些主件與附件的例...