0-1背包问题dp[][]/dp[]
创始人
2025-05-31 11:47:14
0

先推荐个视频

b站算法训练营

一、类型1,重量限制

题目:

给定N个物品,每个物品有一个重量W和一个价值V.你有一个能装M重量的背包.问怎么装使得所装价值最大.每个物品只有一个.

输入:

输入的第一行包含两个整数n, m,分别表示物品的个数和背包能装重量。

以后N行每行两个数Wi和Vi,表示物品的重量和价值

其中数据规模和约定:1<=N<=200,M<=5000.

输出:

输出1行,包含一个整数,表示最大价值。

思路1二维数组

  1. 思路:

动态规划问题

打表

找动态转换方程

dp[i][j]表示背包容量为j,第i个物品时的最大价值

i表示从物品1到物品i;j表示背包容量为j

我们可以从第一个物品开始,求出j=1到10时的最大价值

再找第二个物品,从j=1到10时的最大价值

再找第三个物品......

dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])

2、二维数组代码:

#include
#include
#include
using namespace std;
int n, m;
int weight[210], value[210];
int dp[210][5010];
int main() {cin >> n >> m;for (int i = 1; i <= n; i++) {cin >> weight[i] >> value[i];}for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {if (weight[i] <= j) {dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);}elsedp[i][j] = dp[i - 1][j];}}cout << dp[n][m];return 0;
}

思路2一维数组

  1. 思路

从上面的表可以看出,第i个物品时,求最大价值只与i-1个物品时最大价值有关,所以可以用一维数组dp[j]来表示背包容量为j时的最大价值。

dp[j]=max(dp[j],dp[j-weight[i]]+value[i])

之所以倒推是因为,递推关系是用i-1来推出的i,所以求i时,i-1还在。

如果正推,那就是用新的i推出新的i,就变成了多次取第i个物品

正推图:

  1. 代码

#include
#include
#include
using namespace std;
int n, m;
int weight[210], value[210];
int dp[5010];
int main() {cin >> n >> m;for (int i = 1; i <= n; i++) {cin >> weight[i] >> value[i];}for (int i = 1; i <= n; i++) {for (int j = m; j >=weight[i]; j--) {dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);}}cout << dp[m];return 0;
}

二、类型2,重量和体积限制

题目:

有5件物品,它们分别有价值,体积和重量。

为了把它们装进一个背包里,其体积和重量必须符合要求,不超过背包要求的容量。

请问背包内装物品,其最大价值是多少。

输入:

第一行是两个数,V,W(V,W<=10000),表示背包可负载的最大体积和重量

输入包括5行。

每行都包含三个数字,pi,vi,wi,(pi,vi,wi<=10000)表示价值,体积和重量。

输出:

包括一个数,表示可装下的最大价值。

思路:

数据较少,可直接枚举

时间复杂度2^5

每件物品只有两种状态,0(不拿)、1(拿)

代码:

#include
#include
#include
using namespace std;
int v, w,pr,vo,we,mx;
int price[6], volume[6],weight[6];
int dp[6];
void func(int u) {if (u <= 5) {dp[u] = 0;func(u + 1);dp[u] = 1;func(u + 1);}else {pr = 0; vo = 0; we = 0;for (int i = 1; i <= 5; i++) {pr += price[i] * dp[i];vo += volume[i] * dp[i];we += weight[i] * dp[i];}if (pr > mx && vo <= v && we <= w) {mx = pr;}}
}
int main() {cin >> v >> w;for (int i = 1; i <= 5; i++) {cin >> price[i] >> volume[i] >> weight[i];}func(1);cout << mx << endl;return 0;
}

相关内容

热门资讯

数据结构与算法——堆的基本存储 目录 一、概念及其介绍 二、适用说明 三、结构图示 四、Java 实例代码 五.堆和栈的区别 一、...
Vue.js语法详解:从入门到... Vue.js是一个流行的JavaScript框架,用于构建用户界面。它的核心特性包括数...
“江淮河汉”的意思 “江淮河汉”的意思 成语拼音: [jiāng huái hé hàn] ...
“英雄气短”的意思 “英雄气短”的意思 成语拼音: [yīng xióng qì duǎn] ...
“神龙见首不见尾”的意思 “神龙见首不见尾”的意思 成语拼音: [shén lóng jiàn shǒu bù j...
“老生常谈”的意思 “老生常谈”的意思 成语拼音: [lǎo shēng cháng tán] ...
Application 初始化... Application 的 onCreate 和 attachBaseContextApplicat...
Unity 热更新技术 | (... 🎬 博客主页:https://xiaoy.blog.csdn.net ...
01分布式电源接入对配电网影响... 说明书 MATLAB代码:分布式电源接入对配电网影响分析 关键词:分布式...
“付诸一炬”的意思 “付诸一炬”的意思 成语拼音: [fù zhū yī jù] ...
四字开头的成语 四字开头的成语四字开头的成语1  四通五达  四通八达  四停八当  四体不勤  四体不勤  四体百...
“过目成诵”的意思 “过目成诵”的意思 成语拼音: [guò mù chéng sòng] ...
“年复一年”的意思 “年复一年”的意思 成语拼音: [nián fù yī nián] ...
2023-第十四届蓝桥杯冲刺计... 💬前言 💡本文以目录形式列举大纲,可根据题目点击跳转 dz...
JavaScript查找数组内... 需求:查找数组内元素6是否存在 let arr = [1, 3, 6, 5, ...
Redis缓存穿透、击穿、雪崩... 系列文章目录 Spring Cache的使用–快速上手篇 分页查询–Java项目实战篇 全局异常处理...
新婚四字成语祝福语 新婚四字成语祝福语  在朋友或者同学的新婚上,为了表达真挚的`祝福,有哪些四字成语祝福语?下面是小编...
带有邻字的成语及解释 带有邻字的成语及解释  以“邻”字开头的成语及解释如下:  [邻女詈人] 比喻各为其主。詈,指“骂”...
“寻风捉影”的意思 “寻风捉影”的意思 成语拼音: [xún fēng zhuō yǐng] ...
Java开发 | 内部类 | ... 目录 1.内部类 1.1内部类的简单创建  1.2内部类的分类 1.2.1普通内部类 1.2.2静态...