You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

##AcWing 4. 多重背包问题 I

一、题目描述

N 种物品和一个容量是 V 的背包。

i 种物品最多有 s_i 件,每件体积是 v_i,价值是 w_i

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

输入格式 第一行两个整数,NV,用空格隔开,分别表示物品种数和背包容积。

接下来有 N 行,每行三个整数 v_i,w_i,s_i,用空格隔开,分别表示第 i 种物品的体积、价值和数量。

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

数据范围 0<N,V≤100 0<v_i,w_i,s_i≤100

输入样例

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

输出样例

10

二、分析过程

  • 状态表示:f[i][j] 集合:从前i个物品中选,总体积不超过j的所有选法 属性:max(集合中每种选法总价值)
  • 状态计算 集合划分的过程,和完全背包很像,但不像完全背包有无穷多个,而是有数量限制
f[i][j]=max(f[i][j],f[i-1][j-w[i]*k]+v_i*k)  \ \ k \in \{0,1,2,3,...\}

三、实现代码(二维数组)

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int n, m;

int f[N][N];
int main() {
    cin >> n >> m;

    for (int i = 1; i <= n; i++) { // 讨论每个物品
        int w, v, s;
        cin >> v >> w >> s;
        for (int j = 0; j <= m; j++)                   // 讨论每个剩余的体积
            for (int k = 0; k <= s && v * k <= j; k++) // 讨论加入的个数
                f[i][j] = max(f[i][j], f[i - 1][j - k * v] + w * k);
    }
    printf("%d\n", f[n][m]);
    return 0;
}

四、实现代码(一维数组)

#include <bits/stdc++.h>

using namespace std;

const int N = 110;

int n, m;
int f[N];

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        int v, w, s;
        cin >> v >> w >> s;
        for (int j = m; j >= v; j--)
            for (int k = 0; k <= s && k * v <= j; k++)
                f[j] = max(f[j], f[j - v * k] + w * k);
    }
    printf("%d\n", f[m]);
    return 0;
}