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


题目传送门
这道题目跟 \(01\) 背包很像,只不过是在 \(01\) 背包的基础上加上了一个重量限制。

\(01\) 背包的动态转移方程是

\(f[i, j] = max (f[i ? 1, j], f[i ? 1, j ? v_i] + w_i)\)

那么这个多了个重量,那么可以再开一维,变成三维

\(f[i, j, k] = max (f[i ? 1, j, k], f[i ? 1, j ? v_i, k ? m_i] + w_i)\)

\(01\) 背包,它也可以压缩一下空间,于是变成了

\(f[j][k] = max(f[j - v[i]][k - m[i]] + w[i], f[j][k])\)
动态转移方程出来了,那么写代码也就轻松了。

#include 

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

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