知識點:01揹包(多種姿勢:二維實現+一維實現+滾動陣列實現+揹包裝滿+輸出最優方案)
---
四月份還沒寫,不能這麼荒廢了呀,趕緊水一篇吧,哈哈。前些日子回顧了DP的一些基礎,就做一下整理吧,從0-1揹包開始。
本節回顧0-1揹包的基本模型,關於它的實現有很多種寫法,這裡對不同實現做個簡單列舉,主要是寫程式碼練手了,主要有以下幾方面內容:
==0-1揹包問題定義 & 基本實現
==0-1揹包使用滾動陣列壓縮空間
==0-1揹包使用一維陣列
==0-1揹包恰好背滿
==0-1揹包輸出最優方案
========================================
0-1揹包問題定義 & 基本實現
問題:有個容量為V大小的揹包,有很多不同重量weight[i](i=1..n)不同價值value[i](i=1..n)的物品,每種物品只有一個,想計算一下最多能放多少價值的貨物。
DP的關鍵也是難點是找到最優子結構和重疊子問題,進而找到狀態轉移方程,編碼就相對容易些。最優子結構保證每個狀態是最優的,重疊子問題也即n狀態的求法和n-1狀態的求法是一樣的;DP在實現上一般是根據狀態轉移方程自底向上的迭代求得最優解(也可以使用遞迴自頂向下求解)。
回到0-1揹包,每個物體i,對應著兩種狀態:放入&不放入揹包。揹包的最優解是在面對每個物體時選擇能夠最大化揹包價值的狀態。0-1揹包的狀態轉移方程為
1 |
f(i,v)
= max{ f(i-1,v), f(i-1,v-c[i])+w[i] }
|
f(i,v)表示前i個物體面對容量為v時揹包的最大價值,c[i]代表物體i的cost(即重量),w[i]代表物體i的價值;如果第i個物體不放入揹包,則揹包的最大價值等於前i-1個物體面對容量v的最大價值;如果第i個物體選擇放入,則揹包的最大價值等於前i-1個物體面對容量v-cost[i]的最大價值加上物體i的價值w[i]。
對於實現,一般採用一個二維陣列(狀態轉移矩陣)dp[i][j]來記錄各個子問題的最優狀態,其中dp[i][j]表示前i個物體面對容量j揹包的最大價值。
下面給出0-1揹包的基本實現,時間複雜度為O(N*V),空間複雜度也為O(N*V),初始化的合法狀態很重要,對於第一個物體即f[0][j],如果容量j小於第一個物體(編號為0)的重量,則揹包的最大價值為0,如果容量j大於第一個物體的重量,則揹包最大價值便為該物體的價值。為了能單步驗證每個狀態的最優解,程式最後將狀態轉移矩陣的有效部分輸出到了檔案。
程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
#include
<iostream>
using
namespace std;
/*
0-1揹包 版本1
*
Time Complexity O(N*V)
*
Space Complexity O(N*V)
*
設 V <= 200 N <= 10
*
狀態轉移方程:f(i,v) = max{ f(i-1,v), f(i-1,v-c[i])+w[i] }
*/
int
maxValue[11][201]; /* 前i個物體面對容量j的最大價值,即子問題最優解 */
int
weight[11];
int
value[11];
int
V, N;
void
main()
{
相關推薦知識點:01揹包(多種姿勢:二維實現+一維實現+滾動陣列實現+揹包裝滿+輸出最優方案)文章作者:Yx.Ac 文章來源:勇幸|Thinking (http://www.ahathinking.com) 轉載請註明,謝謝合作。 --- 四月份還沒寫,不能這麼荒廢了呀,趕緊水一篇吧,哈哈。前些日子回顧了DP的一些基礎,就做一下整理吧,從0-1揹包開始。 本節回顧0- 筆試Java實現單例設計模式(最優方案)public class SingletonTest { private SingletonTest() //建構函式私有化 { js小數相加、相乘失去精度問題解析詳解(最優方案)var CMX = CMX || {}; /** ** 加 **/ CMX.add = function (arg1, arg2) { var r1, r2, m, c; try { r1 = arg1.toString().split(".")[1].length; } catc LVS模式四:FULLNAT模式(環境構造:編譯核心)fullnat模式原理圖: FULLNAT模式原理: 1、client主機(cip)將請求發往前端的負載均衡器(vip),請求報文源地址是CIP,目標地址為VIP。負載均衡器收到報文後,發現請求的是在規則裡面存在的地址,那麼它將客戶端請求報文的源MAC地址改為自己DIP的MAC地址,目 ZOJ 3593 One Person Game(ExGcd + 最優解)題解i++ 題解 mes tdi spa code game max include 思路:題意轉化為求 (ax+by=dis) || (ax+cy=dis) || (bx+cy=dis) 三個式子有解時的最小|x| + |y|。顯然求解特解x,y直接用擴展歐幾裏得,那麽怎麽求 牛客網《劍指Offer》 程式設計 25.複雜連結串列的複製 (最優解法)題目描述 輸入一個複雜連結串列(每個節點中有節點值,以及兩個指標,一個指向下一個節點,另一個特殊指標指向任意一個節點),返回結果為複製後複雜連結串列的head。(注意,輸出結果中請不要返回引數中的節點引用,否則判題程式會直接返回空) 解題思路 這次使用時間複雜度為O(n 貪心演算法(最優裝載)貪心演算法 貪心本質:一個貪心演算法總是作出當前最好的選擇,也就是說,它期望通過區域性最優選擇從而得到全域性最優的解決方案。 貪心演算法祕籍: (1)貪心策略 首先確定貪心策略,選擇當前看上去最好的一個方案。 (2)區域性最優解 根據貪心策略,一步一步地得到區域性最優解。 (3)全域 順序佇列求解迷宮(最優解)【問題描述】 以一個mXn的長方陣表示迷宮,0和1分別表示迷宮中的通路和障礙。設計一個程式,對任意設定的迷宮,求出一條從入口到出口的通路,或得出沒有通路的結論。 【任務要求】 實現佇列求解迷宮從入口到出口的最短通路。 【測試資料】 迷宮的測試資料如下: 淺析 AngularJS 全球化最優方案(六)本節是最後一節關於AngularJS的國際化和本地化方案討論,具體會和大家聊下目前有哪些第三方庫,以及優缺點。 首先談談國際化,AngularJS自帶國際化支援,提供了一些語言的國際化資原始檔檔案,具體的覆蓋面,大家可以去官網查詢。 下面聊聊怎麼使用這些資原始檔,一般來說 動態規劃演算法-----找零錢問題(求最優解)動態規劃演算法通常用於求解具有某種最優性質的問題。動態規劃演算法與分治法類似,其基本思想都是將待求解問題分解成若干個子問題,先求解子問題,然後從這些子問題的解得到原問題的解。與分治法不同的是,適合於用動態規劃求解的問題,經分解得到的子問題往往不是互相獨立的。如果 城市交通網(動態規劃,最短路徑,輸出最短路徑)【例9.5】城市交通路網 時間限制: 1000 ms 記憶體限制: 65536 KB 【題目描述】 下圖表示城市之間的交通路網,線段上的數字表示費用,單向通行由A->E。試用動態規劃的最優化原理求出A->E的最省費用。 如圖:求v1到v1 HDU 2612 (BFS+取最優解)1.題意:你約你喜歡的妹子去KFC,你們想找一家最近的,使得你和妹子到KFC所用時間和最短。 2.思路:相當於進行兩次BFS搜尋,可以從每個KFC當做起始點 出發搜尋Y和M,也可以從Y和M出發搜尋到達每個KFC的時間,然後用一個數組儲存到達每個kfc的總時間,找到最小值輸出 軟考之系統集成項目管理工程師(包含2009-2018歷年真題詳解+第二版考試輔導教程+官方指定最新版教程)工程 https follow 系統集成 分享圖片 get 項目管理 baidu 指定 軟考之系統集成項目管理工程師(包含2009-2018歷年真題以及答案詳解、系統集成項目管理工程師教程第2版-清華大學出版社-高清PDF,官方指定用書),持續更新後續年份的資料。請點贊!! 揹包問題 動態規劃 滾動陣列實現比起別的講解揹包問題的部落格,這一篇更加註重在於理解如何用滾動陣列實現動態規劃。 揹包問題特徵 1.存在類似一個集合的求解所有子集的特性。關於一個集合的所有子集,會直接考慮每一個集合元素存在或不存在於子集中,最後對於一個由n個元素構成的集合,其子集數目是 限界分支法:01揹包問題,優先順序佇列(包含解的追蹤)前面提到: 不知道大家注意到沒有?上述實現方式沒有使用單位體積價值的排序,和之前提到01揹包回溯法基於單位體積價值實現不一樣(先裝單位體積價值高的)。 我們網上經常看到都是基於以上實現的,到底這個用有什麼好處了?實際上基於排序的單位體積價值是一個非常精確的限界函式 基於優先順序佇 限界分支法(佇列方式)追蹤解:01揹包問題追蹤解 追蹤解,上述實現的情況下,解都在最後一層,根本不知道之前的路徑是怎樣的,廣度優先搜尋,同一個緯度,假如不加指標判斷的話,根本不知道最優解是選擇的哪一個,所以需要同一個緯度的每一個結點,記住他之前的路徑,才能在最優解的時候之前是怎麼走過來的,每一個結點用一個數組記錄路徑,這樣實現的 回溯法(深度優先)剪枝和分支限界法(寬度優先)剪枝對比:01揹包問題限界函式: CurValue + rest <= BestValue 回溯法(深度優先)剪枝 # 遞迴方式 class pack_01_back_prune_test: def __init__(self,N,V,C,W): self 限界分支法(實際上沒有剪枝,介紹的是廣度優先搜尋):01揹包問題,佇列實現方式(FIFO)限界分支法:佇列實現方式 前面已經介紹過限界分支法大部分是基於廣度優先搜尋,廣度優先搜尋一般藉助於佇列實現,剪枝的情況可以藉助於優先順序佇列。 實現如下: #%% class FIFO_01_Pack: def __init__(self,N,V,C,W): hdu2546:飯卡(01揹包)http://acm.hdu.edu.cn/showproblem.php?pid=2546 Problem Description 電子科大本部食堂的飯卡有一種很詭異的設計,即在購買之前判斷餘額。如果購買一個商品之前,卡上的剩餘金額大於或等於5元,就一定可以購買成功(即使購買後卡上餘額 HDU 2546:飯卡(01揹包)飯卡 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 41634 Accepted Submission( |