动态规划 学习
发布于 2026-04-06更新于 2026-11-14727 字5 分钟 · 阅读时间
void solve() { int n, v; scanf("%d%d", &n, &v); vector<pair<int, int> > a(n); vector<vector<int> > dp(n + 1, vector<int>(v + 1, 0)); // 行为物品,列为剩余容量 for (int i = 0; i < n; ++i) { scanf("%d%d", &a[i].first, &a[i].second); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= v; j++) { if (j >= a[i - 1].first) { dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - a[i - 1].first] + a[i - 1].second); } else { dp[i][j] = dp[i - 1][j]; } } } printf("%d\n", dp[n][v]);}Q:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - a[i - 1].first] + a[i - 1].second);为什么第一个是没装它的价值,第二个是装了它的价值
这行代码是动态规划算法中的一部分,用于解决背包问题。在这个问题中,我们试图在不超过背包容量的情况下,最大化背包中物品的总价值。
dp[i][j]"Test file/C++ main.cpp")表示考虑前i个物品,当背包容量为j时的最大价值。
dp[i - 1][j]"Test file/C++ main.cpp")表示不考虑当前第i"Test file/C++ main.cpp")个物品,即不将当前物品装入背包时的最大价值。这是因为我们已经考虑了前i-1个物品,并且背包的容量仍然为j。
dp[i - 1][j - a[i - 1].first] + a[i - 1].second"Test file/C++ main.cpp")表示考虑将当前第i个物品装入背包时的最大价值。这里a[i - 1].first是当前物品的重量(或占用的容量),a[i - 1].second是当前物品的价值。首先,我们查看在装入当前物品之前,背包容量为j-a[i-1].first时的最大价值(即dp[i - 1][j - a[i - 1].first]),然后加上当前物品的价值a[i - 1].second。
max(dp[i - 1][j], dp[i - 1][j - a[i - 1].first] + a[i - 1].second)这个表达式的含义是:对于每个物品i和每个可能的背包容量j,我们都要决定是装入这个物品以增加总价值,还是不装入这个物品以保持当前的总价值。我们选择这两种情况中价值更大的一个,以确保在考虑到当前物品时,对于给定的背包容量j,我们能够获得最大的价值。
j - a[i - 1].first实际上表示的是在当前背包容量为j的情况下,如果选择装入第i个物品(注意数组是从0开始的,所以第i个物品在数组中的索引是i - 1,那么装入这个物品之前背包的剩余容量。这个表达式是用来计算如果决定装入第i个物品,背包中还能剩余多少容量。在动态规划的状态转移方程中,
dp[i][j]表示考虑前i个物品,当背包容量为j时的最大价值。当考虑是否将第i个物品装入背包时,如果选择装入,那么背包的剩余容量将会减少a[i - 1].first个物品的重量)。因此,j - a[i - 1].first实际上是在查找在剩余容量下,不考虑当前物品(即只考虑前i-1时的最大价值,然后加上当前物品的价值a[i - 1].second,以此来更新dp[i][j]的值。所以,
j - a[i - 1].first并不直接表示“不装入第i个物品的价值”,而是用于计算如果决定装入第i个物品,背包在装入这个物品之前的剩余容量,进而用这个剩余容量去查询之前计算的最大价值,以决定是否装入这个物品是最优的选择。
分享你的想法,与大家交流讨论
Twikoo 加载失败
Twikoo 脚本加载失败