01 背包

题目链接:洛谷 P1048

题目大意

给定一个最大重量为 $V$ 的背包,和 $n$ 个物品。每个物品有一个重量和价值。现在问在背包可以装下的范围内,最大的价值是多少。

朴素 DP

我们定义 dp[i][j] 为到第 $i$ 个物品,背包的重量为 $j$ 的最大价值。

我们可以得出状态转移方程:
$$
\text{dp[i][j] = max(dp[i – 1][j], dp[i – 1][j – w[i]] + v[i])}
$$

其中 $\text{w[i]}$ 是重量,$\text{v[i]}$ 是价值。

我们会发现,这样的代码的空间复杂度是 $O(nV)$,时间复杂度是 $O(nV)$,在有一些题目中会 MLE。

于是,我们有了以下优化。

状态压缩 DP

我们发现 dp[i][j] 肯定是从 dp[i - 1] 转移过来的,于是我们可以尝试把 $i$ 的这一维度压缩掉,只剩背包重量这个的维度。

我们可以得出状态转移方程:
$$
\text{dp[i] = max(dp[j], dp[j – w[i]] + v[i])}
$$

但是,状态压缩方程有一点需要注意的。

在递推的时候,我们需要注意第二层虚幻需要从大到小遍历。

因为如果是正着推的话,我们会发现方程就变成:
$$
\text{dp[i][j] = max(dp[i – 1][j], dp[i][j – w[i]] + v[i])}
$$

因为 $dp[j – w[i]]$ 已经被更新了。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    int dp[10005] = {0}, n, V, v, w;
    cin >> V >> n;
    for (int i = 1; i <= n; i++) {
        cin >> w >> v;
        for (int j = V; j >= w; j--) {
            dp[j] = max(dp[j], dp[j - w] + v);
        }
    } 
    cout << dp[V];
    return 0;
}
本文链接:https://ztrztr.top/archives/500
版权声明:本文 《01 背包》 为 ztrztr 原创。著作权归作者所有。
转载说明:联系作者或者评论区留言获得转载授权,并注明转载地址。
暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇