动态规划基础:背包问题
一、0-1 背包问题
**概述:**给定一组物品,每个物品有重量和价值,在限定的总重量内选择物品,使得总价值最大。每个物品最多只能选择一次(选或不选)。
**问题描述:**物品重量数组 v,物品价值数组 w,背包容量 W。在不超过背包容量的情况下,问能装入物品的最大价值。
**思考方式:**0-1 背包问题可以按照状态转移图来分析。
二维状态解法:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int v[N], w[N]; // v 表示体积,w 表示价值
int dp[N][N]; // dp[i][j] 表示前 i 个物品放入容量为 j 的背包的最大价值
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= m; j++) {
dp[i][j] = dp[i - 1][j]; // 不选第 i 个物品
if (j >= v[i]) {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]); // 选第 i 个物品
}
}
}
cout << dp[n][m];
return 0;
}
空间优化思路:
将状态 dp[i][j] 优化到一维 dp[j]。定义 dp[j] 为容量为 j 时的最优解。
注意枚举背包容量 。这是因为在一维情况下,如果正序更新, 可能已经被当前轮次更新过,导致重复选取同一物品,违背 0-1 背包规则。逆序则保证了使用的是上一轮的状态。


