题目传送门

问题:二维费用\(01\)背包问题

题目描述
\(n\) 件物品 和 一个容量为 \(V\) 的背包,背包最大承重是 \(M\)
每件物品只能 用一次,第 \(i\) 件物品的 体积\(v_i\)重量\(m_i\),价值 是 \(w_i\)
求解一个选物品的 方案,使得 总体积 不超过 \(V\)总重量 不超过 \(M\) 的,且 总价值 最大

分析
每件物品只能 用一次 因此是个 01背包模型

费用一共有两个,一个是 体积,一个是 重量,因此是个 01背包二维费用问题

本题是一道裸题,直接上 闫氏DP分析法

闫氏DP分析法

AcWing 8. 二维费用的背包问题

初始状态:f[0][0][0]

目标状态:f[n][V][M]

一、三维数组解朴素解法

#include <bits/stdc++.h>

using namespace std;
const int N = 1010;
const int M = 110;
int n;//n个物品
int V;//包的体积上限
int Z;//包的重量上限
int v1[N];//体积
int v2[N];//重量
int w[N];//价值
int f[N][M][M];//三维的dp数组,描述前i个物品,体积j,重量k时的最大价值

//问题:二维费用的01背包问题[三维数组解法]
/**
 状态转移方程:

 (1)当剩余的空间j不能装下当前物品i,即j<v1[i]时不能选择i物品。
 f[i,j,k]=f[i−1,j−vi,k−mi]+wi

 (2)当剩余的重量k不能装下当前物品i,即k<v2[i]时不有选择i物品。
 f[i,j,k]=f[i−1,j−vi,k−mi]+wi

 (3)当j>=v1[i]&&k>=v2[i]时,可以选择要i,还是不要i。
 f[i,j,k]=max(f[i−1,j,k],f[i−1,j−vi,k−mi]+wi)
 */

/**
4 5 6
1 2 3
2 4 4
3 4 5
4 5 6

答案:8
*/
int main() {
    cin >> n >> V >> Z;
    //体积,重量,价值
    for (int i = 1; i <= n; i++) cin >> v1[i] >> v2[i] >> w[i];
    //遍历每一个物品
    for (int i = 1; i <= n; i++)
        for (int j = 0; j <= V; j++)//体积
            for (int k = 0; k <= Z; k++) //重量
                //第i个物品不能要
                if (j < v1[i] || k < v2[i]) f[i][j][k] = f[i - 1][j][k];
                    //第i个物品可以要,还要继续讨论要还是不要
                else f[i][j][k] = max(f[i - 1][j - v1[i]][k - v2[i]] + w[i], f[i - 1][j][k]);
    //输出
    printf("%d", f[n][V][Z]);
    return 0;
}


二、二维数组空间优化解法

#include <bits/stdc++.h>

using namespace std;
const int N = 1010;
const int M = 110;
int n;//n个物品
int V;//体积上限
int Z;//重量上限
int v1[N];//每个物品的体积
int v2[N];//每个物品的重量
int w[N];//每个物品的价值
int f[M][M];//二维的dp数组,描述前i个物品

signed main() {
    cin >> n >> V >> Z;
    //体积,重量,价值
    for (int i = 1; i <= n; i++) cin >> v1[i] >> v2[i] >> w[i];
    //遍历每一个物品
    for (int i = 1; i <= n; i++)
        for (int j = V; j >= v1[i]; j--)     //由大到小遍历每一个体积
            for (int k = Z; k >= v2[i]; k--) //由大到小遍历每一个重量
                f[j][k] = max(f[j - v1[i]][k - v2[i]] + w[i], f[j][k]);//动态转移方程,01 背包的思路
    //输出
    printf("%d", f[V][Z]);
    return 0;
}


相关文章: