初学dp之01背包

刚开始学算法的时候,就经常听到大犇们讨论什么dpdp的,叫什么动态规划,然后感觉这东西很深奥

于是对它就产生了某种畏惧心理

等到学的时候也没弄懂,没想到现在要在这个破嵙重新捡起来

概念

大致就是递归的思路,把大问题分解成小问题,就这样

贴个模版题先😋

7-3 小Z卸货

作者 zyc

单位 山东科技大学

小Z卸货
小Z是一个卸货工人,他每天都会去码头卸货,每件货物都有其价值vi和其卸货的时间ti,问他在T的时间内卸下来的所有的货物的总价值最大是多少

输入格式:

第1行有2个整数T(1≤T≤1000)和 M(1≤M≤100),用一个空格隔开,T代表总共能够用来卸货的时间,M代表码头上货物的数目。
接下来的M行每行包括两个正整数t(1≤t≤100) v(1≤v≤100),用空格分隔

输出格式:

输出在规定的时间内卸下的货物的最大总价值。

输入样例:

在这里给出一组输入。例如:

1
2
3
4
32 3
30 100
29 1
2 2

输出样例:

在这里给出相应的输出。例如:

1
102

不管是什么采药采果子卸货啥的,这类问题一般可以枚举出所有情况(可以暴力)

就是做出取舍,有一定价值的同时也会造成一定负面影响

为什么叫01背包呢,就是因为对于一个物品,我们只有拿或者不拿两种情况,即0与1

试图理解

引入一个二维数组m[ ][ ]

再引入别人的一个博客

w为质量即上文提到的“负面影响”,他会占用容量;v为价值

面对每个物品,我们只有选择拿取或者不拿两种选择,不能选择装入某物品的一部分,也不能装入同一物品多次。
解决办法:声明一个 大小为 m[n][c] 的二维数组,m[ i ][ j ] 表示 在面对第 i 件物品,且背包容量为 j 时所能获得的最大价值 ,那么我们可以很容易分析得出 m[i][j] 的计算方法,
(1). j < w[i] 的情况,这时候背包容量不足以放下第 i 件物品,只能选择不拿
m[ i ][ j ] = m[ i-1 ][ j ]
(2). j>=w[i] 的情况,这时背包容量可以放下第 i 件物品,我们就要考虑拿这件物品是否能获取更大的价值。
如果拿取,m[ i ][ j ]=m[ i-1 ][ j-w[ i ] ] + v[ i ]。 这里的m[ i-1 ][ j-w[ i ] ]指的就是考虑了i-1件物品,背包容量为j-w[i]时的最大价值,也是相当于为第i件物品腾出了w[i]的空间。
如果不拿,m[ i ][ j ] = m[ i-1 ][ j ] , 同(1)
究竟是拿还是不拿,自然是比较这两种情况那种价值最大。
————————————————

                版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/qq_67764134/article/details/129903263

就是如果容量够放这个物品的话,那就去找不放这个物品(i-1)并且容量刚好够够这个物品(j-w[i])的最优解

即m[ i ][ j ]=m[ i-1 ][ j-w[ i ] ] + v[ i ]

然后让他和不放他的情况比较,取较大者

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

小z卸货题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
using namespace std;
int main()
{
long long n,V;
cin>>V>>n;
long long w[10000],t[10000],f[1001][1001];
for(int i=1;i<=n;i++)
{
cin>>t[i]>>w[i];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=V;j++)
{
if(t[i]>j) f[i][j]=f[i-1][j];
else
f[i][j]=max(f[i-1][j],f[i-1][j-t[i]]+w[i]);
}
}
cout<<f[n][V];
return 0;
}
Edited on

Give me a cup of [coffee]~( ̄▽ ̄)~*

GoodNut WeChat Pay

WeChat Pay

GoodNut Alipay

Alipay

GoodNut PayPal

PayPal