elric
19 次阅读
约 3 分钟 · 727 字
动态规划 学习

01背包

C++
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 脚本加载失败