首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >01背包问题

01背包问题

作者头像
GeekLiHua
发布2025-01-21 13:38:56
发布2025-01-21 13:38:56
1810
举报
文章被收录于专栏:JavaJava

01背包问题/动态规划(快速入门)

前言:背包问题是dp(动态规划)经典入门题目集合,里面的01背包问题也是一切的起点,作者当初学习此算法的时候,把各种教学视频看了十几遍,加上老师的讲解,还有很多博客,最后还是一知半解,但是随着时间积累,慢慢的在许久之后明白了这个算法,这也是我的一个学习算法的建议,在入门一个算法的时候,不必短时间内理解它的含义,记住模板,然后在未来的某个时刻,会理解它的。

以题目入门

01背包问题

N 件物品和一个容量是 V的背包。每件物品只能使用一次。

i件物品的体积是 vi,价值是wi

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。 输出最大价值。

输入格式

第一行两个整数,NV,用空格隔开,分别表示物品数量和背包容积。

接下来有 N行,每行两个整数 vi,wi,用空格隔开,分别表示第 ii 件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤1000 0<vi,wi≤1000

输入样例

代码语言:javascript
复制
4 5
1 2
2 4
3 4
4 5

输出样例

代码语言:javascript
复制
8

提交代码

代码语言:javascript
复制
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m; // 物品的数量,背包的容积
int v[N], w[N]; // v是每个物品体积的数组,w是每个物品价值的数组
int f[N][N];  

int main()
{
    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)
        {
            f[i][j] = f[i - 1][j];
            if (j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
        }
    }
    cout << f[n][m] << endl;
    return 0;
}

解析

我给的代码是一个01背包问题的标准模板,下面的便是我对该模板的解释。

首先对题目分析,有N件物品,和一个容器为V的背包,,然后每件物品只能拿一次,然后每件物品的体积和价值不一样,求怎么拿才是价值最大的,这也是一个很现实的问题。

f[n][m]是什么意思了,拿f[i][j]的意思为,意思很简单,就是对于容量为i,背包容量为j的时候,最大的价值是多少。

关键代码

代码语言:javascript
复制
for (int  i = 1; i <= n; ++ i)
{
    for (int j = 0; j <= m; ++ j)
    {
        f[i][j] = f[i - 1][j];
        if (j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
    }
}
cout << f[n][m] << endl;

最后输出f[n][m]的含义是,当物品数量为n和背包容积为m的时候,最大的价值。

然后外面的两层for循环是枚举,n,m的情况,其实dp问题可以很简单,主要是需要找到对应的数学表达式,这个肯定比高中数学题目简单。

这个题目的数学表达式是什么了。

f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i])

f[i - 1][j]的含义为:当物品数量为i-1,然后背包容量为j(这里代表的是第i件物品不选)的时候的最大价值,如果第i件物品不选的话,

那么f[i][j]就直接等于f[i - 1][j]

f[i - 1][j - v[i]] + w[i]的含义为:相比于f[i - 1][j]区别在于,他选了第i件,第i件的体积大小为v[i],然后价值为w[i],因为选了

i件所以j-v[i],体积变小了,然后对于他的价值多了w[i]

所以每次最后的表达式就是f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]),只是需要注意的是,j不一定每次大于v[i],

为了防止数组下标小于0,所以需要一个if判断一下.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01背包问题/动态规划(快速入门)
    • 以题目入门
    • 解析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档