解题思路

  1. 这是一个多重背包问题,每种物品有指定的数量限制
  2. 可以将多重背包转化为0-1背包来解决:
    • 对每种物品,最多可以选择其数量上限个
    • 使用逆序遍历避免重复计算
  3. 状态定义:
    • 表示容量为 时能获得的最大价值
  4. 状态转移:

代码

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n, v;
    cin >> n >> v;
    
    vector<int> m(n);    // 物品数量
    vector<int> w(n);    // 物品体积
    vector<int> s(n);    // 物品价值
    vector<int> dp(v + 1, 0);  // dp数组
    
    // 读取每种物品的信息
    for(int i = 0; i < n; i++) {
        cin >> m[i] >> w[i] >> s[i];
    }
    
    // 多重背包
    for(int i = 0; i < n; i++) {           // 遍历物品
        for(int k = 0; k < m[i]; k++) {    // 遍历物品数量
            for(int j = v; j >= w[i]; j--) {// 逆序遍历容量
                dp[j] = max(dp[j], dp[j-w[i]] + s[i]);
            }
        }
    }
    
    cout << dp[v] << endl;
    return 0;
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();  // 物品种类
        int v = sc.nextInt();  // 背包容量
        
        int[] m = new int[n];  // 物品数量
        int[] w = new int[n];  // 物品体积
        int[] s = new int[n];  // 物品价值
        int[] dp = new int[v + 1];  // dp数组
        
        // 读取每种物品的信息
        for(int i = 0; i < n; i++) {
            m[i] = sc.nextInt();
            w[i] = sc.nextInt();
            s[i] = sc.nextInt();
        }
        
        // 多重背包
        for(int i = 0; i < n; i++) {
            for(int k = 0; k < m[i]; k++) {
                for(int j = v; j >= w[i]; j--) {
                    dp[j] = Math.max(dp[j], dp[j-w[i]] + s[i]);
                }
            }
        }
        
        System.out.println(dp[v]);
    }
}
def solve_knapsack(n, v, items):
    # 初始化dp数组
    dp = [0] * (v + 1)
    
    # 处理每种物品
    for i in range(n):
        m, w, s = items[i]  # 数量、体积、价值
        # 对每个物品可用的数量进行处理
        for k in range(m):
            # 逆序遍历容量
            for j in range(v, w-1, -1):
                dp[j] = max(dp[j], dp[j-w] + s)
    
    return dp[v]

# 读取输入
n, v = map(int, input().split())
items = []
for _ in range(n):
    m, w, s = map(int, input().split())
    items.append((m, w, s))

# 输出结果
print(solve_knapsack(n, v, items))

算法及复杂度

  • 算法:动态规划(多重背包转化为0-1背包)
  • 时间复杂度: - 为物品种类, 为背包容量, 为每种物品的数量
  • 空间复杂度: - 需要一个容量大小的 数组