解题思路

这是一个动态规划问题,具体要求:

  1. 个点上有 个物品,每个物品有体积 和价值
  2. 有两个袋子 ,容量分别为
  3. 从左到右遍历物品,可以选择放入当前使用的袋子或不放
  4. 可以在任意时刻切换使用的袋子,但一旦收起袋子 就不能再使用
  5. 求两个袋子中物品总价值的最大值

解决方案:

  1. 使用01背包的思想
  2. 分别计算以每个位置为分界点时的最优解
  3. 正向计算袋子 的最优解,反向计算袋子 的最优解
  4. 枚举分界点,找到最大值

代码

#include<bits/stdc++.h>
using namespace std;

int main() {
    int n, A, B, maxval = 0;
    int bagA[1002] = {0}, bagB[1002] = {0};
    int ansA[1002] = {0}, ansB[1002] = {0};
    int v[1002], w[1002];
    
    // 输入数据
    cin >> n >> A >> B;
    for(int i = 1; i <= n; i++) {
        cin >> v[i] >> w[i];
        // 正向计算袋子A的dp值
        for(int j = A; j >= v[i]; j--) {
            bagA[j] = max(bagA[j], bagA[j - v[i]] + w[i]);
        }
        ansA[i] = bagA[A];  // 记录到第i个物品时的最优解
    }
    
    // 反向计算袋子B的dp值
    for(int i = n; i >= 1; i--) {
        for(int j = B; j >= v[i]; j--) {
            bagB[j] = max(bagB[j], bagB[j - v[i]] + w[i]);
        }
        ansB[i] = bagB[B];  // 记录从第i个物品开始的最优解
    }
    
    // 枚举分界点,找到最大值
    for(int i = 0; i <= n; i++) {
        maxval = max(ansA[i] + ansB[i + 1], maxval);
    }
    
    cout << maxval << endl;
    return 0;
}
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int A = sc.nextInt();
        int B = sc.nextInt();
        
        int[] v = new int[1002];
        int[] w = new int[1002];
        int[] bagA = new int[1002];
        int[] bagB = new int[1002];
        int[] ansA = new int[1002];
        int[] ansB = new int[1002];
        int maxval = 0;
        
        // 输入数据并正向计算袋子A
        for(int i = 1; i <= n; i++) {
            v[i] = sc.nextInt();
            w[i] = sc.nextInt();
            for(int j = A; j >= v[i]; j--) {
                bagA[j] = Math.max(bagA[j], bagA[j - v[i]] + w[i]);
            }
            ansA[i] = bagA[A];
        }
        
        // 反向计算袋子B
        for(int i = n; i >= 1; i--) {
            for(int j = B; j >= v[i]; j--) {
                bagB[j] = Math.max(bagB[j], bagB[j - v[i]] + w[i]);
            }
            ansB[i] = bagB[B];
        }
        
        // 枚举分界点
        for(int i = 0; i <= n; i++) {
            maxval = Math.max(ansA[i] + ansB[i + 1], maxval);
        }
        
        System.out.println(maxval);
    }
}
def solve():
    n, A, B = map(int, input().split())
    v = [0] * 1002
    w = [0] * 1002
    bagA = [0] * 1002
    bagB = [0] * 1002
    ansA = [0] * 1002
    ansB = [0] * 1002
    maxval = 0
    
    # 输入数据并正向计算袋子A
    for i in range(1, n + 1):
        v[i], w[i] = map(int, input().split())
        for j in range(A, v[i] - 1, -1):
            bagA[j] = max(bagA[j], bagA[j - v[i]] + w[i])
        ansA[i] = bagA[A]
    
    # 反向计算袋子B
    for i in range(n, 0, -1):
        for j in range(B, v[i] - 1, -1):
            bagB[j] = max(bagB[j], bagB[j - v[i]] + w[i])
        ansB[i] = bagB[B]
    
    # 枚举分界点
    for i in range(n + 1):
        maxval = max(ansA[i] + ansB[i + 1], maxval)
    
    print(maxval)

solve()

算法及复杂度

  • 算法:动态规划(01背包变种)
  • 时间复杂度: - 需要两次背包dp
  • 空间复杂度: - 需要存储两个背包的状态