動態規劃-07依賴揹包
阿新 • • 發佈:2019-01-01
按照《揹包九講》的順序,本文主要講其第七講-依賴揹包,所謂“依賴揹包”即指揹包物件有主附件,類似的解釋之前在“二維費用揹包”中提到過,不過這裡的主附件是從屬關係,即選擇主件,必須要選擇附件,而附件的類別又可以有很多種,同樣的附件也可以有附件,這樣如此反覆,即會形成一個“樹形DP”,其結果和考慮的情況將呈指數型增長,所以無法寫成類似於“01揹包”的方程式,但如果給定限定條件,我們同樣也可以將其轉換成類似“01揹包”或者“完全揹包”等形式來解決。
本文設計的題目為牛客網的華為OJ題——購物單。
問題描述:
王強今天很開心,公司發給N元的年終獎。王強決定把年終獎用於購物,他把想買的物品分為兩類:主件與附件,附件是從屬於某個主件的,下表就是一些主件與附件的例子:主件 | 附件 |
電腦 | 印表機,掃描器 |
書櫃 | 圖書 |
書桌 | 檯燈,文具 |
工作椅 | 無 |
輸入描述:
輸入的第1行,為兩個正整數,用一個空格隔開:N m
(其中N(<32000)表示總錢數,m(<60)為希望購買物品的個數)從第2行到第m+1行,第j行給出了編號為j-1的物品的基本資料,每行有3個非負整數v p q(其中v表示該物品的價格(v<10000),p表示該物品的重要度(1~5),q表示該物品是主件還是附件。如果q=0,表示該物品為主件,如果q>0,表示該物品為附件,q是所屬主件的編號)輸出描述:
輸出檔案只有一個正整數,為不超過總錢數的物品的價格與重要度乘積的總和的最大值(<200000)。
具體的題目如下:
具體的Java實現程式碼如下:
//這裡用一維陣列進行講解 private static int bp_rely(int m,int n,int[] w,int[] v,int[] q){ int[] c = new int[m+1]; for (int i = 0; i < m+1; i++) { c[i] = 0; } List<Integer> list = new ArrayList<>(); for (int i = 0; i < n; i++) { list.clear(); if (q[i] == 0) { for (int j = m; j >= w[i]; j--) { list.add( Math.max(c[j-w[i]] + v[i], c[j])); c[j] = Math.max(c[j-w[i]] + v[i], c[j]); } }else { for (int j = m; j >= (w[i]+w[q[i]]); j--) { list.add(Math.max(c[j-w[i]-w[q[i]]] + v[q[i]], c[j])); c[j] = Math.max(c[j-w[i]-w[q[i]]] + v[q[i]], c[j]); } } } int max = Collections.max(list); return max; }
上述程式碼中,需要注意的地方是根據判斷q是否為“0”來確定該物件是“主件”還是“附件”,而如果是附件,則必須先購買主件才能購買附件,即下面的程式碼:
Math.max(c[j-w[i]-w[q[i]]] + v[q[i]], c[j]) //w[i]和w[q[i]]分別為主件和附件的價格
上述如果有什麼紕漏或錯誤,歡迎批評指正。