二维背包问题(15-15)

106 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 15 天,点击查看活动详情

今天进行二维背包的基础模型学习。

二维费用的背包问题

题目描述

NN 件物品和一个容量是 VV 的背包,背包能承受的最大重量是 MM

每件物品只能用一次。体积是 viv_i,重量是 mim_i,价值是 wiw_i

求解将哪些物品装入背包,可使物品总体积不超过背包容量,总重量不超过背包可承受的最大重量,且价值总和最大。
输出最大价值。

输入格式

第一行三个整数,N,V,MN,V,M, 用空格隔开,分别表示物品件数、背包容积和背包可承受的最大重量。

接下来有 NN 行,每行三个整数 vi,mi,wiv_i,m_i,w_i,用空格隔开,分别表示第 ii 件物品的体积、重量和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N10000<N≤1000

0<V,M1000<V,M≤100

0<vi,mi1000<v_i,m_i≤100

0<wi10000<w_i≤1000

输入样例

4 5 6
1 2 3
2 4 4
3 4 5
4 5 6

输出样例

8

题目分析

这是一道二维背包模型的问题。

首先分析题目,每件物品的数量为 11,则可以联想到 01背包的解法。

01背包的转移方程为:

f[i][j]=max(f[i1][j],  f[i1][jvi]+wi)f[i][j]=max(f[i-1][j],\; f[i-1][j-v_i]+w_i)

相较于01背包中的物品,二维背包中每个物品除体积外还多了个重量的属性,背包也给出了总体积和总重量两个限制条件。

我们注意到,每件物品的重量和体积是绑定在一起的,即若不选择这件物品,背包在减去相应体积的同时也会减去相应的重量。

自然的,我们可以多开一维数组给重量,转移方程为:

f[i][j][k]=max(f[i1][j][k],  f[i1][jvi][kmi]+wi)f[i][j][k]=max(f[i-1][j][k],\; f[i-1][j-v_i][k-m_i]+w_i)

同样,可以像01背包那样压缩一维,转移方程简化为:

f[i][j]=max(f[i][j],  f[ivi][jmi])f[i][j]=max(f[i][j],\; f[i-v_i][j-m_i])

时间复杂度为 O(vm)O(vm)

Accept代码 O(vm)

#include <bits/stdc++.h>

using namespace std;

const int N = 110;
int f[N][N];

int main()
{
    int n, v, m;
    cin >> n >> v >> m;
    for (int i = 0; i < n; i ++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        
        for (int j = v; j >= a; j --)
            for (int k = m; k >= b; k --)
                f[j][k] = max(f[j][k], f[j - a][k - b] + c);
    }
    cout << f[v][m];
    return 0;
}