0-1背包的变型
dp[i][j]表示考虑了前i个物品,当背包大小为j的时候,剩余的最少空间。
初始化:
起初一个物品都没有放入,所以dp[0][j] = j;
转移方程:
if (a[i] < j) dp[i][j] = min(dp[i - 1][j], dp[j - a[i]]);
else dp[i][j] = dp[i - 1][j];
节省空间的做法:
因为转移方程只涉及到dp[i]和dp[i - 1]的计算,并且在计算计算第 j 位的结果时,只会依赖于 j 之前的结果。所以可以浓缩为一个维度。在遍历的时候,从右往左遍历,就可以消除第一个维度,进行动态维护。
dp[j] = min(dp[j], dp[j - a[i]]);
其中,j是从大到小遍历。
#include <bits/stdc++.h> using namespace std; int main() { int v, n; cin >> v >> n; vector<int> a(n); for (int i = 0; i < n; i++) cin >> a[i]; vector<int> dp(v + 1, 0); for (int i = 0; i <= v; i++) dp[i] = i; for (int i = 0; i < n; i++) { for (int j = v; j >= 0; j--) { if (a[i] <= j) { dp[j] = min(dp[j], dp[j - a[i]]); } } } cout << dp[v] << '\n'; } // 64 位输出请用 printf("%lld")