Acwing-基础算法课笔记之动态规划(背包问题)

这篇具有很好参考价值的文章主要介绍了Acwing-基础算法课笔记之动态规划(背包问题)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、01背包问题

1、概述

  1. 01背包中的0和1指的是放与不放,而且不能出现放多个的情况,背包只能放相同物品中的一个;
  2. 首先是对 d [ i ] [ j ] d[i][j] d[i][j] 数组的解释,该数组表示的是只看前 i i i 个物品,总体积是 j j j 的情况下,总价值最大是多少;

2、过程模拟

  1. 不选第 i i i个物品,只考虑前 i − 1 i-1 i1个物品, d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j]=dp[i-1][j] dp[i][j]=dp[i1][j]
  2. 选第 i i i个物品, d p [ i ] [ j ] = d p [ i − 1 ] [ j − v [ i ] ] dp[i][j]=dp[i-1][j-v[i]] dp[i][j]=dp[i1][jv[i]]
  3. d p [ i ] [ j ] = m a x { 1 , 2 } dp[i][j]=max\{1,2\} dp[i][j]=max{1,2}
  4. 初始条件,一个物品都不考虑 d p [ 0 ] [ 0 ] = 0 dp[0][0]=0 dp[0][0]=0

背包的最大容量为 6 6 6

物品 体积 v v v 价值 w w w
A A A 2 2 2 3 3 3
B B B 3 3 3 5 5 5
C C C 4 4 4 6 6 6
0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6
0 0 0 0 0 0 0 0 0 0
1 1 1 A ( 2 , 3 ) A(2,3) A(2,3) 0
2 2 2 B ( 3 , 5 ) B(3,5) B(3,5) 0
3 3 3 C ( 4 , 6 ) C(4,6) C(4,6) 0

⇓ \Downarrow
∙ \bullet 对于每一个单元格 i . w e i g h t > j i.weight>j i.weight>j是否成立,按行填写

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6
0 0 0 0 0 0 0 0 0 0
1 1 1 A ( 2 , 3 ) A(2,3) A(2,3) 0 0 3 3 3 3 3
2 2 2 B ( 3 , 5 ) B(3,5) B(3,5) 0
3 3 3 C ( 4 , 6 ) C(4,6) C(4,6) 0

⇓ \Downarrow

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6
0 0 0 0 0 0 0 0 0 0
1 1 1 A ( 2 , 3 ) A(2,3) A(2,3) 0 0 3 3 3 3 3
2 2 2 B ( 3 , 5 ) B(3,5) B(3,5) 0 0 3 5 5 8 8
3 3 3 C ( 4 , 6 ) C(4,6) C(4,6) 0

⇓ \Downarrow

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6
0 0 0 0 0 0 0 0 0 0
1 1 1 A ( 2 , 3 ) A(2,3) A(2,3) 0 0 3 3 3 3 3
2 2 2 B ( 3 , 5 ) B(3,5) B(3,5) 0 0 3 5 5 8 8
3 3 3 C ( 4 , 6 ) C(4,6) C(4,6) 0 0 3 5 6 8 9

滚动dp一维数组版

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6
0 0 0 0 0 0 0 0 0 0

⇓ \Downarrow

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6
1 1 1 A ( 2 , 3 ) A(2,3) A(2,3) 0 0 3 3 3 3 3

⇓ \Downarrow

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6
2 2 2 B ( 3 , 5 ) B(3,5) B(3,5) 0 0 3 5 5 8 8

⇓ \Downarrow

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6
3 3 3 C ( 4 , 6 ) C(4,6) C(4,6) 0 0 3 5 6 8 9

二、完全背包问题

1、概述

n n n件物品,每件物品的重量为 w [ i ] w[i] w[i],价值为 c [ i ] c[i] c[i]。现有一个容量为 V V V,的背包,问如何选取物品放入背包,使得背包物品的总价值最大。其中每件物品有无穷件。
既然这样,不妨像0-1背包问题那样,先写出状态转移方程,从源头上摸索。

2、闫氏dp分析完全背包问题

d p { 状态表示 ( i , j ) { 集合:所有只从前 i 个物品中选,总体积不超过 j 的方案的集合 属性: m a x 状态计算 d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , f [ i − 1 ] [ j − v ] + w 、 f [ i − 1 ] [ j − 2 v ] + 2 w 、 . . . . . . ) , d p [ i ] [ j − v ] = m a x ( d p [ i − 1 ] [ j − v ] , f [ i − 1 ] [ j − 2 v ] + w 、 f [ i − 1 ] [ j − 3 v ] + 2 w 、 . . . . . . ) + w ,两式组合 d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , f [ i ] [ j − v ] + w ) 如下图选第 i 个物品 dp\begin{cases} 状态表示(i,j)\begin{cases} 集合:所有只从前i个物品中选,总体积不超过j的方案的集合 \\ 属性:max \end{cases} \\ 状态计算dp[i][j]=max(dp[i-1][j],f[i-1][j-v]+w、f[i-1][j-2v]+2w、......),dp[i][j-v]=max(dp[i-1][j-v],f[i-1][j-2v]+w、f[i-1][j-3v]+2w、......)+w,两式组合dp[i][j]=max(dp[i-1][j],f[i][j-v]+w)如下图选第i个物品 \end{cases} dp 状态表示(i,j){集合:所有只从前i个物品中选,总体积不超过j的方案的集合属性:max状态计算dp[i][j]=max(dp[i1][j],f[i1][jv]+wf[i1][j2v]+2w......)dp[i][jv]=max(dp[i1][jv],f[i1][j2v]+wf[i1][j3v]+2w......)+w,两式组合dp[i][j]=max(dp[i1][j],f[i][jv]+w)如下图选第i个物品

Acwing-基础算法课笔记之动态规划(背包问题),Acwing基础算法课笔记,算法,笔记,动态规划

3、过程模拟

例如:

容量j
组号 物品 体积v 价值w 0 1 2 3 4 5 6 7
0 (无) 0 0 0 0 0 0 0 0 0 0
1 小古银手办 2 1 0 0 1 1 2 2 3 3
2 平板电脑 3 3 0 0 1 3 3 4 6 6
3 笔记本电脑 4 5 0 0 1 3 5 5 6 8
4 无价之宝 5 0 0 0 1 3 5 5 6 8

规律:
∙ \bullet j < v i j<v_i j<vi的时候, w i , j = w i − 1 , j w_{i,j}=w_{i-1,j} wi,j=wi1,j(解释:如果当前物品装不进背包,最大价值和前 i − 1 i-1 i1个物品的最大价值一样)
∙ \bullet j ≥ v i j\ge v_i jvi的时候, w i , j = m a x ( w i − 1 , j w_{i,j}=max(w_{i-1,j} wi,j=max(wi1,j不装,装 ) ) )(解释:如果装的下,在装和不装中选最大价值)

代码模板

int m = 0;
int n = 0;
cin >> m >> n;
int v[40] = {};
int w[40] = {};
for (int i = 1; i <= n; i ++){
    cin >> v[i] >> w[i];
}
int dp[40][210] = {};
for (int i = 1; i <= n; ++ i) {
    for (int j = 1; j <= m; ++ j) {
        if (j < v[i]) {
           dp[i][j] = dp[i - 1][j];
        }
        else {
           dp[i][j] = max(dp[i - 1][j], dp[i][j - v[i]] + w[i])
        }
    }
}
cout << "max = " << dp[n][m] <<endl;

优化版代码:

int m = 0;
int n = 0;
cin >> m >> n;
int v[40] = {};
int w[40] = {};
for (int i = 1; i <= n; i ++){
    cin >> v[i] >> w[i];
}
int dp[40][210] = {};
for (int i = 1; i <= n; ++ i) {
    for (int j = v[i]; j <= m; ++ j) {
        dp[j] = max(dp[j], dp[j - v[i]] + w[i])
    }
}
cout << "max = " << dp[n][m] <<endl;

三、多重背包问题

1、概述

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大,但要注意的是,每件要取物品不能超过他给出的最大数量。

2、过程模拟

for(int i = 0; i < n; i ++)
   for(int j = m; j >= v[i]; j --)
      dp[j] = max(dp[j], dp[j - v[i]] + w[i], dp[j - 2 * v[i]] + 2 * w[i],......)//每件物品可以不去,可以取1个,或者取2个等等。

3、多重背包问题的优化版本

假设有一种物品有 s s s 件,若要将其拆分开来,则从 1 1 1 开始循环,每进行一次循环就乘 2 2 2,并每循环一次就减去迭代的变量 i i i,代码如下:

while (n--) {
	int v, w, s;
	scanf("%d%d%d", &v, &w, &s);
	for (int i = 1; i <= s; i *= 2) {
		s -= i;
		goods.push_back({ v * i,w * i });
	}
	if (s > 0)goods.push_back({ v * s,w * s });
}

分组背包问题

1、概述

N N N组物品和一个容量是 V V V的背包。每组物品有若干个,同一组内的物品最多只能选一个。每件物品的体积是 v i j v_{ij} vij,价值是 w i j w_{ij} wij,其中 i i i是组号, j j j是组内编号。

2、过程模拟

例如:
∙ \bullet 一个组只能选一个物品

组号 物品 体积v 价值w
1 小古银手办 2 1
平板电脑 3 3
2 笔记本电脑 4 5
3 无价之宝 5 0

以下是动态模拟:
∙ \bullet 每个组都有装和不装两种情况
∙ \bullet 如果装某个组的话,这个组只能装一次文章来源地址https://www.toymoban.com/news/detail-854940.html

容量j
组号 0 1 2 3 4 5 6 7
0 0 0 0 0 0 0 0 0
1 0
2 0
3 0

3、代码演示

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 110;
int n, m;
int v[N], w[N], dp[N];
int main() {
	scanf("%d%d", &n, &m);
	while (n--) {
		int s;
		scanf("%d", &s);
		for (int i = 0; i < s; i++)
			scanf("%d%d", &v[i], &w[i]);
		for (int j = m; j >= 0; j--) {
			for (int k = 0; k < s; k++) {
				if (j >= v[k]) {
					dp[j] = max(dp[j], dp[j - v[k]] + w[k]);
				}
			}
		}
	}
	printf("%d", dp[m]);
	return 0;
}

到了这里,关于Acwing-基础算法课笔记之动态规划(背包问题)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python 算法基础篇:背包问题的动态规划解法

    背包问题是计算机科学中一个重要的组合优化问题,动态规划是解决该问题的高效算法技术。本篇博客将重点介绍背包问题的动态规划解法,包括状

    2024年02月16日
    浏览(30)
  • 【第二十五课】动态规划:完全背包问题(acwing-3 / 公式推导 / 思路理解 / 优化 / c++代码)

    目录 思路 朴素代码 优化 公式推导上  二维代码  一维代码 公式理解上   在开始看完全背包问题之前,可能需要先了解01背包及其解决办法。 指路👇 【第二十五课】动态规划:01背包问题(acwing-2 / 思路 / 含一维数组优化 / c++代码) 这个问题和01背包的区别就是 每件物品可以

    2024年03月19日
    浏览(49)
  • acwing算法基础之动态规划--DP习题课1

    暂无。。。 暂无。。。 题目1 :最长严格上升子序列,要求时间复杂度为 O ( n l o g n ) O(nlogn) O ( n l o g n ) 。 解题思路:保存每个长度下的最小的结尾元素值,遍历数组元素时,通过二分找到它,然后更新它即可,返回len。 该算法的关键步骤如下: 定义向量 vec , vec[i] 表示

    2024年02月03日
    浏览(38)
  • 算法学习笔记(动态规划——01背包)

    先来聊聊动态规划,动态规划是分治法的一种体现,把一个问题分解成若干个子集,通过当前状态,经过操作得到下一个状态,最后得到最优问题解的一种方法。 步骤: 设定状态,保存状态 根据状态设定转移方程 确定边界 其中的01背包解决的是关于选择的动态规划问题,

    2024年03月25日
    浏览(38)
  • 算法系列--动态规划--背包问题(1)--01背包介绍

    💕\\\"趁着年轻,做一些比较cool的事情\\\"💕 作者:Lvzi 文章主要内容:算法系列–动态规划–背包问题(1)–01背包介绍 大家好,今天为大家带来的是 算法系列--动态规划--背包问题(1)--01背包介绍 背包问题是动态规划中经典的一类问题,经常在笔试面试中出现,是非常 具有区分度 的题

    2024年04月16日
    浏览(37)
  • 算法系列--动态规划--背包问题(3)--完全背包介绍

    💕\\\"Su7\\\"💕 作者:Lvzi 文章主要内容:算法系列–动态规划–背包问题(3)–完全背包介绍 大家好,今天为大家带来的是 算法系列--动态规划--背包问题(3)--完全背包介绍 链接: 完全背包 可以发现完全背包问题和01背包问题还是特比相似的 分析: 完全背包问题 是 01背包问题 的推广

    2024年04月25日
    浏览(31)
  • 【AcWing算法基础课】第五章 动态规划(未完待续)

    本专栏文章为本人AcWing算法基础课的学习笔记,课程地址在这。如有侵权,立即删除。 dp问题的优化 :在基本形式dp上作等价变形。 dp问题的解题方法 : 1)状态表示 集合 属性:最大值/最小值/数量。 2)状态计算 集合划分(不重不漏) 题目链接: 2. 01背包问题 - AcWing题库

    2024年02月12日
    浏览(34)
  • 【算法-动态规划】0-1 背包问题

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月08日
    浏览(34)
  • acwing算法基础之动态规划--线性DP和区间DP

    线性DP:状态转移表达式存在明显的线性关系。 区间DP:与顺序有关,状态与区间有关。 题目1 :数字三角形。 解题思路:直接DP即可, f[i][j] 可以来自 f[i-1][j] + a[i][j] 和 f[i-1][j-1] + a[i][j] ,注意 f[i-1][j] 不存在的情况(最后一个点)和 f[i-1][j-1] 不存在的情况(第一个点)。

    2024年02月04日
    浏览(40)
  • 算法学习17-动态规划01:背包问题

    提示:以下是本篇文章正文内容: 提示:这里对文章进行总结: 💕💕💕

    2024年04月27日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包