記錄(乾貨還是有一些的) 最近三天沒怎麼做題(只看理論不敲**是不行的...orz...),看了一些關於dp的文章,主要是關於揹包的相關問題。
著重看了01揹包和完全揹包。[還捎帶看了些dfs和bfs,裸題看了看,能基本複寫**,完全不會優化(記憶化算嗎...嘿嘿嘿),剪枝啥的好遙遠...
發現dp有三種基本的方法:1.記憶化搜尋(遞迴)2.通過遞推規律(正向、反向)來dp 3.通過狀態轉移來dp:
w[i+1]=f; (w[i]為i時狀態,fj()為對某狀態的第j種決策,f{}為取不同決策結果中最優的函式(規劃))
這個方程是分析dp問題的關鍵嗎,從這個基礎上可以進行優化(主要的優化是對空間的優化,因為能寫出狀態轉移方程來的話,一般都能找到不用遞迴的方法,前提是不懶...,所以時間上的優化不太常見,唯一見到過的是01揹包中資料限制改變導致的策略調整)空間上優化主要手段是重複利用陣列(這個好像在遞迴呼叫中也可以,不過沒見到相關的題就不瞎說了),例如在01揹包和完全揹包中dp[i][j]中因為i(不同種類物品的編號)在變化的過程中原來的不用再記錄了故重新賦值給相同j的從而把二維陣列壓縮成一維陣列,還有就是如果狀態轉移方程中是i到i+1這種相鄰狀態轉移到話可以考慮區分奇偶(位運算&1即可),每次轉移都釋放然後重新賦值,用滾動陣列來做。
算了還是放一下吧...
重複利用陣列優化空間:
#include#includeconst int m=10000;
//01揹包
int dp[m+10];//dp[i+1][j]裝前j種物品質量為j的物品可能的最大的價值
//v[i]、w[i]為編號為i的物品的價值量和質量,w為限重
void solve()
//完全揹包,沿用01揹包的記號,注意遞推的方向是不同的
int dp[m+10];//dp[i+1][j(同01揹包)裝前j種物品質量為j的物品可能的最大的價值
//一開始的狀態轉移方程是帶k的(挑選特定一種物品的個數),通過恒等變形推過來的,和01揹包的思路不完全相同,時間複雜度是o(n*w)
void solve()
printf("%d\n",dp[n&1][w]);
}
DP之揹包學習記錄 一
昨天看了01揹包,完全揹包,和多重揹包這三個問題,然後呢,01和完全的區別在於順序還是倒序.今天偷點懶,寫完解題報告就滾床睡,剛才看到了whud大牛的部落格,好棒,真的好棒,自己要加油啦,在2015年希望有個質的飛越。揹包問題是dp問題的乙個分支,所有揹包問題呢,都是可以劃分到01揹包這個最簡單基礎...
DP之揹包學習記錄(三)
說完了01揹包,完全揹包,我們接著學習多重揹包,還是介紹下問題題目有 n種物品和乙個容量為 v的揹包。第 i種物品最多有 n i 件可用,每件費用是 c i 價值是 w i 求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。我們還是老樣子,先寫出多重揹包的類似於01揹包的狀...
DP學習之完全揹包
有 n nn 種物品和乙個容量是 v 的揹包,每種物品都有無限件可用。第 i ii 種物品的體積是v iv i vi 價值是 w iw i wi 求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。資料範圍 0 v 1000 00v 10 000 wi 1000 00 wi 1...