搞了兩天的dp了,對01揹包又有了新的理解。網上有很多資料,可能都比我寫的好,只是記錄一下我的理解。
**編譯過不了,只是記錄揹包問題的思想。
參考:《演算法入門經典》
首先乙個引例:
物品無限的揹包問題——dag 硬幣問題
就是加了乙個權值的dag,ans = max(ans,dp(c-v[i])+w[i]);
由於01揹包問題,按照dag模型的話,不能表示每個物品是否拿過,這要求我們決策有序化。
決策的分層階段,d(i,j)當前階段是 i ,揹包容量是 j ,
邊界條件:
d(i,j) = 0; i>n;
答案 d(1,c);
狀態轉移方程:
d(i,j) = max(d(i+1,j),d(i+1,j-v[i])+w[i]);
還有一種就是對稱的定義:
前1~i個物品都放入時揹包容量為j 是的最優值。
f(i,j) = max(f(i-1,j),f(i-1,j-v[i])+w[i]);
答案是 f(n,c);
然後就是滾動陣列了:
這裡的dp順序很有講究。
f是從上到下,從右到左的遞推的。
計算f(i,j)時,f[j]儲存的是f(i-1,j)的值,f[j-v] 儲存的是 f(i-1,j-v)的值。
這樣狀態轉移方程就出來了:
f[j] = max(f[j],f[j-v]+w);
#include usingnamespace
std;
#define num 2000
#define c 100000
intd[num][c];
int n; //
物品種量
///物品無限 —— dag 硬幣問題
intd[c];
bool
vis[c];
int dp(int
c) }
}int
main()
}///規劃方向
///對稱定義
///把1~i放到揹包裡面去
for(int i=1;i<=n;i++)
}///滾動陣列
memset(f,0,sizeof
(f));
for(int i=1;i<=n;i++) }}
return0;
}
揹包 01揹包
01揹包 有n種物品與承重為m的揹包。每種物品只有一件,每個物品都有對應的重量weight i 與價值value i 求解如何裝包使得價值最大。dp i,v 表示前i個物體 包括第i個 面對容量為v的揹包的最大價值,c i 代表物體i的重量,w i 代表物體i的價值 如果第i個物體不放入揹包,則揹包...
最大團問題 0 1揹包 再談分支限界
對於分支限界,其實思想和回溯很像,只是具體的實現方法不一樣。回溯用到遞迴,是深度優先搜尋 分支限界是用最大堆進行迴圈,是廣度優先搜尋。1.最大團問題 給出乙個無向連通圖,求出其最大完全子圖的節點數 分析 每乙個節點進行分析,如果可以放進去,則定為1,放入左節點,要是不能放進去,則定為0,放入右節點。...
揹包專題 01揹包
暑假集訓開始了,按照隊裡的分配,我是弄dp的,嘛,於是我又一次的開始了從01揹包開始學習,昨天將杭電的幾道01揹包重新做了一遍,下面講講我自己對於01揹包的理解。首先01揹包題目的雛形是 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。...