給定n種物品和一個揹包,物品i(1≤i≤n)的重量是wi,其價值爲vi,揹包的容量爲C。對每種物品只有兩種選擇:裝入揹包或者不裝入揹包。如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?ios
這是一個經典的動態規劃問題。容易證實,其知足最優子結構性質:即設(x1, x2, ..., xn)是該問題的一個最優解(其中xi=1表示放入物品i,xi=0表示不放入),則(x1, x2, ..., xk-1, xk+1, ..., xn)必定是原問題去除物品k後獲得的子問題的最優解。函數
首先咱們看一下揹包問題的一個特例:0/1揹包問題。(例題見於:Openjudge-0/1揹包問題)spa
在此問題中,每種物品只有一件。因而,對於第i件物品,只有兩種選擇:放入揹包或者不放入。最優解的遞推表達式:code
其中fk(y)表示揹包容量爲y且只能取前k種物品的條件下,能夠放入的物品的最大總價值。blog
爲了在求得最大總價值後,找到對應的最優解,還須要標記函數。令標記函數Ik(y)表示揹包容量爲y且只能取前k種物品的條件下,放入的物品的最大序號,則有ci
因而,咱們能夠寫出0/1揹包問題的代碼:get
『C++』it
#include <iostream> #include <algorithm> using namespace std; #define maxn 200 #define maxw 200 int n, C; void TraceBack(int (*I)[maxn], int *w, int W) { int x[maxn] = {}; int y = W, k = n; while (I[k][y] != 0) { while (I[k][y] == k) { y -= w[k]; x[k]++; } k = I[k][y]; } for (int i = 1; i <= n; i++) printf("%d\n", x[i]); return; } int main() { while (cin >> n >> C) { int w[maxn] = {}, v[maxn] = {}; int F[maxn][maxw] = {}; int I[maxn][maxw] = {}; int W[maxn][maxn] = {}; for (int k = 1; k <= n; k++) { cin >> w[k] >> v[k]; } for (int k = 1; k <= n; k++) { for (int y = 0; y <= C; y++) { if (y >= w[k] && F[k - 1][y] < F[k - 1][y - w[k]] + v[k]) { F[k][y] = F[k - 1][y - w[k]] + v[k]; W[k][y] = W[k - 1][y - w[k]] + w[k]; I[k][y] = k; } else { F[k][y] = F[k - 1][y]; W[k][y] = W[k - 1][y]; I[k][y] = I[k - 1][y]; } } } printf("%d\n", F[n][C]); TraceBack(I, w, W[n][C]); } //system("pause"); return 0; }
若同一種物品能夠放入多個,則標記函數同上,而只需將遞推方程改成以下便可:io