1. 程式人生 > >動態規劃解二維多重揹包問題

動態規劃解二維多重揹包問題

揹包問題

揹包問題是一個很經典的演算法問題,根據其複雜程度不同又可分為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[]))。