動態規劃解二維多重揹包問題
阿新 • • 發佈:2019-02-20
揹包問題
揹包問題是一個很經典的演算法問題,根據其複雜程度不同又可分為01揹包問題、完全揹包問題、多重揹包問題、二維揹包問題等等。本文講一講二維多重揹包問題的動態規劃解法。
01揹包問題
有N件物品和一個容量為V的揹包。第i件物品的體積是a[i],價值是w[i]。求解將哪些物品裝入揹包可使價值總和最大
完全揹包問題
有N種物品和一個容量為V的揹包,每種物品都有無限件可用。第i種物品的體積是a[i],價格是w[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大
多重揹包問題
有N種物品和一個容量為V的揹包。第i種物品最多有n[i]件,每件體積是a[i],價值是w[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大
二維揹包問題
有N件物品和一個容量為V,載重為U的揹包。第i件物品的體積是a[i],重量是b[i],價值是w[i]。求解將哪些物品裝入揹包可使價值總和最大
二維多重揹包問題
二維多重揹包問題即是多重揹包問題和二維揹包問題的結合——有N種物品和一個容量為V,載重為U的揹包。第i種物品最多有n[i]件,每件體積是a[i],重量是b[i],價值是w[i]。求解將哪些物品裝入揹包可使價值總和最大
void backpack(int V, int U, int a[], int b[], int w[], int n[], int N) {
int i, j, k, l, *x, ***dp;
//初始化
dp = (int ***) malloc(sizeof(int **) * (N + 1));
for (i = 0; i <= N; ++i) {
dp[i] = (int **) malloc(sizeof(int *) * (V + 1));
for (j = 0; j <= V; ++j) {
dp[i][j] = (int *) malloc(sizeof(int) * (U + 1));
}
}
for (i = 0; i <= N; ++i) {
for (j = 0; j <= V; ++j) {
memset(dp[i][j], 0, sizeof(int) * (U + 1));
}
}
x = (int *) malloc(sizeof(int) * N); //列印方案
memset(x, 0, sizeof(int) * N);
//求解
for (i = 1; i <= N; ++i) {
for (j = a[i - 1]; j <= V; ++j) {
for (k = b[i - 1]; k <= U; ++k) {
dp[i][j][k] = dp[i - 1][j][k];
for (l = 1; l <= n[i - 1]; ++l) {
if (l * a[i - 1] <= j && l * b[i - 1] <= k) {
dp[i][j][k] =
dp[i][j][k]
> (dp[i - 1][j - l * a[i - 1]][k
- l * b[i - 1]] + l * w[i - 1]) ?
dp[i][j][k] :
(dp[i - 1][j - l * a[i - 1]][k
- l * b[i - 1]] + l * w[i - 1]);
} else {
break;
}
}
}
}
}
//列印
j = V;
k = U;
for (i = N; i > 0; --i) {
if (dp[i][j][k] > dp[i - 1][j][k]) {
for (l = 1; l * a[i - 1] <= j && l * b[i - 1] <= k; ++l) {
if (dp[i][j][k]
== (dp[i - 1][j - l * a[i - 1]][k - l * b[i - 1]]
+ l * w[i - 1])) {
x[i - 1] = l;
j -= l * a[i - 1];
k -= l * b[i - 1];
break;
}
}
}
}
printf("best value:%d\n", dp[N][V][U]);
printf("best solution:");
for (i = 0; i < N; ++i)
printf("%d ", x[i]);
printf("\n");
}
以上是最基礎的解法,空間複雜度O(NVU),時間複雜度O(NVU*sum(n[]))。