传送门:https://www.acwing.com/problem/content/4880/

题目描述

有一个为n的背包和m + 1种物品,每种物品都有无限多个。

物品种类编号为0~m。

第i种物品的体积为vi,价值为wi。

在使用背包装入物品时,每种物品的限重如下:

  • 第0种物品:重量忽略不计,在装入时没有重量限制。
  • 第1~m种物品:第i种物品的单个重量为hi,如果该种物品的装入总重量超过li,则视为超重。

现在,请你挑选物品装入背包,要求

  • 所有装入物品的总体积不得超过背包容量。
  • 所有存在重量限制的物品均不得超重。
  • 满足以上所有条件的前提下,所有装入物品的总价值尽可能大。

输出总价值的最大可能值。

注意审题,不要将n, m的含义弄混。

输入格式

第一行包含四个整数n, m, v0, w0。

接下来m行,每行包含四个整数li, hi, vi, wi。

输出格式

一个整数,表示总价值的最大可能值。

数据范围

前4个测试点满足 1≤n≤100,1≤m≤2。

所有测试点满足1≤n≤1000,1≤m≤10。

1≤li,hi,vi,wi≤100。

输入样例1:

10 2 2 1
7 3 2 100
12 3 1 10

输出样例1:

241

输入样例2:

100 1 25 50
15 5 20 10

输出样例2:

200

就是一个有个数限制的多重背包,把个数替换成l / h就可以了;因为只有第一个可以无限取,所以将第一个物品可取的个数设为无穷大。

#include <bits/stdc++.h>

using namespace std;

const int N = 1010, inf = 0x3f3f3f3f;

int v[N], w[N], s[N];
int dp[N][N];

int main() {
    int V, n;
    cin >> V >> n;
    cin >> v[1] >> w[1];
    s[1] = inf;
    n += 1;
    for (int i = 2; i <= n; ++i) {
        int l, h;
        cin >> l >> h >> v[i] >> w[i];
        s[i] = l / h;
    }

    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j <= V; ++j) {
            for (int k = 0; k <= s[i] && k * v[i] <= j; ++k) {
                dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i] * k] + w[i] * k);
            }
        }
    }
    cout << dp[n][V];

    return 0;
}