从01背包说起(上)

简介: 从01背包说起(上)

目录

引入

1.什么是动态规划?

2.什么是背包问题?

3.什么是01背包?

模板题

1.题面

2.思路

Ⅰ为何不可用贪心

Ⅱ状态转移方程

3.代码

下期预告


引入

1.什么是动态规划?

动态规划(英语:Dynamic programming,简称 DP),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。

核心思想: 通过将问题拆分成一个一个小问题,记录过往结果,减少重复运算。

举个栗子:

A : "1+1+1+1+1+1+1+1 =?"

A : "上面等式的值是多少"

B : 计算 "8"

A : 在上面等式的左边写上 "1+" 呢?

A : "此时等式的值为多少"

B : 很快得出答案 "9"

A : "你怎么这么快就知道答案了"

A : "只要在8的基础上加1就行了"

A : "所以你不用重新计算,因为你记住了第一个等式的值为8!动态规划算法也可以说是 '记住求过的解来节省时间'"


感谢🙇‍

@四舍五入两米高的小晨

2.什么是背包问题?

背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。相似问题经常出现在商业、组合数学,计算复杂性理论、密码学和应用数学等领域中。也可以将背包问题描述为决定性问题,即在总重量不超过W的前提下,总价值是否能达到V?它是在1978年由Merkle和Hellman提出的。

常见分类:

01背包

完全背包

多重背包

分组背包

3.什么是01背包?

01背包是背包问题中最简单的问题。01背包的约束条件是给定几种物品,每种物品有且只有一个,并且有权值和体积两个属性。在01背包问题中,因为每种物品只有一个,对于每个物品只需要考虑选与不选(0与1)两种情况。如果不选择将其放入背包中,则不需要处理。如果选择将其放入背包中,由于不清楚之前放入的物品占据了多大的空间,需要枚举将这个物品放入背包后可能占据背包空间的所有情况。

对于这类问题,可采用  深搜+剪枝 或 动态规划 的方法,今天我们用动规来AC此题。


模板题

1.题面

这类问题的模板题,有一道十分经典,它是:[NOIP2005 普及组] 采药

【NOIP2005 普及组】采药

题目描述:

       辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”

       如果你是辰辰,你能完成这个任务吗?

输入格式:

第一行有 22 个整数 TT(1 \le T \le 10001≤T≤1000)和 MM(1 \le M \le 1001≤M≤100),用一个空格隔开,TT 代表总共能够用来采药的时间,MM 代表山洞里的草药的数目。

接下来的 MM 行每行包括两个在 11 到 100100 之间(包括 11 和 100100)的整数,分别表示采摘某株草药的时间和这株草药的价值。

输出格式:

输出在规定的时间内可以采到的草药的最大总价值。

输入输出样例

输入:

70 3

71 100

69 1

1 2

输出 :

3

这道题,就是将原始题目换了个故事。原始题:

有一个容量为V的背包,还有n个物体。现在忽略物体实际几何形状,我们认为只要背包的剩余容量大于等于物体体积,那就可以装进背包里。每个物体都有两个属性,即体积w和价值v。

问:如何向背包装物体才能使背包中物体的总价值最大?

2.思路

Ⅰ为何不可用贪心

很多人看到此题第一个反应便是贪心。但为什么这个问题不能用贪心呢?

举个栗子:

我的背包容量为10,而且有4个物体,它们的体积和价值分别为

w1 = 8, v1 = 9

w2 = 3, v2 = 3

w3 = 4, v3 = 4

w4 = 3, v4 = 3

贪心是每一步采取最优拿法,即每一次都优先拿价值与体积比值最大的物体

c1 = v1/w1 = 1.125(最大)

c2 = v2/w2 = 1

c3 = v3/w3 = 1

c4 = v4/w4 = 1

所以优先拿第一个物体,随后背包再也装不下其他物体了,则最大价值为9。

但是这个问题的最优解是取物体2,3,4装进背包,最大价值为3+4+3=10!(9<10)

感谢🙇‍@Iseno_V

所以这个问题不可以用贪心法来处理。

Ⅱ状态转移方程

先设wi表示第i个物品的重量,vi表示第i个物品的价值。

动态规划的核心是状态转移方程。可以发现:最大价值是物品数量i和背包容量j的函数。

设函数f[i][j]表示前i件物品放入容量为j的背包的最大价值,

最终的最大价值就是物品数量i从0增长到n,背包容量j从0增长到m时的f[n][m]值。

前面说了,01背包对于每个物品只需要考虑选与不选(0与1)两种情况。当前容量为j,我们要考虑第i件物品能否放入?是否放入?

①如果当前背包容量j<v[i],不能放入,则f[i][j]=f[i-1][j]

②如果当前背包容量j>=v[i],能放入但是要比较代价,看放入价值高还是不放入价值高。

2.1 如果第i件物品不放入背包,则f[i][j]=f[i-1][j]

2.2 如果第i件物品放入背包,则f[i][j]=f[i-1][j-w[i]]+v[i]

如果第i件物品放入背包,则背包容量还剩j-w[i],所以要取前i-1件物品放入背包剩余容量j-w[i]所获得的最大价值f[i-1][j-w[i]]。如图:

正在上传…

重新上传

因此,得到状态转移方程:

image.gif编辑

3.代码

#include<iostream>
#include<algorithm>
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];//将不能放入第i件物品的情况和能放入但是没放入的情况合并
                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;
}

image.gif


下期预告

01背包优化+ [NOIP2006 提高组] 金明的预算方案

相关文章
|
6月前
|
存储 算法
二叉树进阶-学会层序遍历助你一次刷完leetcode10道题
文章深入探讨了二叉树的层序遍历方法,并展示了如何通过队列实现层序遍历的算法逻辑,同时指出掌握层序遍历技巧可以帮助解决LeetCode上的多道相关题目。
二叉树进阶-学会层序遍历助你一次刷完leetcode10道题
|
9月前
|
算法 Java
用Java实现01背包问题 用贪心算法
用Java实现01背包问题 用贪心算法
157 43
动态规划入门01背包
基本思路: 1.n物品个数,m为背包体积,使用w[i]记录权值,v[i]记录体积,f[i][j]记录选择前i个物体,在不超过j体积下的最优解 最终答案就是f[n][m]; 2.f[i][j]的状态依赖于之前的状态;即f[i[][j]依赖于f[i - 1][j]的状态;也可以理解为所有的状态由f[0][j]推得 f[i][j]的状态不好算出来,但是f[0][j]的状态必定为0,由f[0][j]可以算出f[1][j]的,由f[1][j]又可算出f[2][j]的递推可得出全部。f[1][1] f[2][2] f[3][3]他们每个都减去第i个物品的权值最大值仍不变,最后在加上w[i]即可 即( f[
72 0
从01背包说起(下)
从01背包说起(下)
57 0
LeetCode 周赛 350(2023/06/18)01 背包变型题
**本文已收录到 [AndroidFamily](https://github.com/pengxurui/AndroidFamily),技术和职场问题,请关注公众号 \[彭旭锐] 和 \[BaguTree Pro] 知识星球提问。**
81 0
LeetCode 周赛 350(2023/06/18)01 背包变型题
ACM刷题之路(二十二)多重背包转01背包 HDU 1171
ACM刷题之路(二十二)多重背包转01背包 HDU 1171
|
JSON Java 数据格式
Java游戏任务背包系统设计思路
Java游戏任务背包系统设计思路
463 0
Java游戏任务背包系统设计思路
可能你已经刷了很多01背包的题,但是真的对01背包领悟透彻了吗?,看我这一篇,使君对01背包的理解更进一步【代码+图解+文字描述】
可能你已经刷了很多01背包的题,但是真的对01背包领悟透彻了吗?,看我这一篇,使君对01背包的理解更进一步【代码+图解+文字描述】
|
算法
01背包原理
笔记
123 0
算法刷题第五天(跑路人笔记)<双指针>
算法刷题第五天(跑路人笔记)<双指针>
算法刷题第五天(跑路人笔记)<双指针>