解题思路
这是一个动态规划问题,具体要求:
个点上有
个物品,每个物品有体积
和价值
- 有两个袋子
和
,容量分别为
和
- 从左到右遍历物品,可以选择放入当前使用的袋子或不放
- 可以在任意时刻切换使用的袋子,但一旦收起袋子
就不能再使用
- 求两个袋子中物品总价值的最大值
解决方案:
- 使用01背包的思想
- 分别计算以每个位置为分界点时的最优解
- 正向计算袋子
的最优解,反向计算袋子
的最优解
- 枚举分界点,找到最大值
代码
#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
- 空间复杂度:
- 需要存储两个背包的状态