首页 > 其他分享 >动态规划之01背包问题讲解

动态规划之01背包问题讲解

时间:2022-10-11 15:34:36浏览次数:65  
标签:01 容量 int max 背包 苹果 讲解 dp


给大家附上一个题目吧,便于理解

ctest有n个苹果,要将它放入容量为v的背包。给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值。

输入:每组测试数据第一行为2个正整数,分别代表苹果的个数n和背包的容量v

接下来的n行,每行2个正整数,用空格隔开,分别代表苹果的大小c和价钱w

01背包其实就是遍历所有可能情况  然后取最优的结果   和搜索差不多 不过比搜索快

0 1 背包的方程为dp[i]=max(dp[i-c[j]])+w[j],dp[i]) 

i:表示当前的背包容量

j:是苹果的序号

dp[i]:是容量为i的背包能放的最大价值 

c[j]:序号为j的苹果的大小

w[j]:序号为j的苹果的价值 

这个方程翻译成白话文就是   容量为i的背包的最大价值=(当前背包容量-序号为j的苹果的大小)的最大价值+序号为j的苹果的价值  和 容量为i的背包的当前价值 之间的最大值 

说着比较绕口。慢慢理解

说白了  ,其实就是取与不取的问题 ,如果取了  那么取后的价值要大于我没有取之前的价值 否则我就不要你  (因为同样大小的背包我要装价值更大的啊)

对着这道题举个例子吧

5     10

1      9

4      4

2      6

5      5

10    8

你能根据自己的想法填下表吗  看结果是否和我的一样

 

动态规划之01背包问题讲解_#include

这个结果其实就是根据0-1背包的思想得到的 ,如果你能填 证明你已经入门了

我首先附上0-1背包的代码 


[cpp]  view plain​  ​copy

 ​​print​

for(int i=0;i<n;i++)
{
for(int j=v;j>=0;j--)
{
if(j>=c[i])
dp[j]=max(dp[j-c[i]]+w[i],dp[j]);
}
}



你肯定有几个问题?

1.为什么外层循环是苹果的数目 而不是背包的容量

答:因为每个苹果只能选择一次  如果背包容量在外 

2.外循环是对苹果的遍历 那么内循环为什么是v-》0而不是 从0-》v

这个问题我也迷惑了好久   我们仔细看看动态方程dp[i]=max(dp[i-c[j]])+w[j],dp[i])    我们首先假设  有一个苹果大小为1   价值为9

那么dp[1]=max(dp[1-1]+9,dp[1])=9  是正常的 dp[2]=max(dp[2-1]+9,dp[2])=18..dp[3]=27,dp[4]=36等等  发现问题了吧

所以内循环从0-》v是错误的    如果从v-》0就行了  因为在每个苹果循环的时候 我们要保证当前已经遍历的背包对我未遍历的背包没有影响

看完了这些 分析上面的截图吧

首先是对苹果大小为1  价值为9     背包容量为10.....1  最大价值都为9  背包容量为0  最大价值为0

苹果大小为4 价值为4  

由于我们对每个苹果遍历后 都是当前苹果个数的最优结果   所以当我们遍历完最后一个苹果 那么结果也就是最优化的

就分析这么多吧 

​这道题的传送门 和AC代码​


[cpp]  view plain​  ​copy

 print​​​


#include <stdio.h>
#include <string.h>
int main()
{
int n,v,max,c[1005],w[1005],dp[1005];
while(scanf("%d %d",&n,&v)!=EOF)
{
if(n==0&&v==0)
break;
sizeof(dp));
for(int i=0;i<n;i++)
"%d %d",&c[i],&w[i]);
max=0;
for(int i=0;i<n;i++)
for(int j=v;j>=c[i];j--)
{
// dp[j]=dp[j];
if(dp[j]<dp[j-c[i]]+w[i])
dp[j]=dp[j-c[i]]+w[i];
if(max<dp[j])
max=dp[j];
}
"%d\n",max);
}
return 0;
}

标签:01,容量,int,max,背包,苹果,讲解,dp
From: https://blog.51cto.com/u_15742657/5746440

相关文章

  • CF1420D & gym102012 G
    CF1420D:注意到任意条线段的交集如果非空的话必定是一条线段,且这条线段的左端点一定是某条线段的左端点。很明显先将线段离散化,然后去枚举相交的线段的左端点。我们设\(......
  • LcdTools如何通过PX01把EDP屏的EDID拷贝出来
    PX01点EDP屏在上电过程会自动读取屏EDID,怎么把EDPEDID值拷贝出来呢?在上电时序函数调用SetEdidRdShowEn(ON)指令开启EDID值读取显示功能。如下图  ......
  • navicat远程连接数据库遇到的问题 11001 unknown error
    今天用navicate连接docker中的MySQL数据库时出现了以下的错误原因:输入主机的IP时在后面多打了一个空格键去除空格之后即可正确连接了......
  • 【2022-10-01】连岳摘抄
    23:59清澈的爱,只为中国。                                            ......
  • java.sql.SQLException: ORA-01000: maximum open cursors exceeded;问题的解决方法
    转:https://blog.csdn.net/ALEX_wxy/article/details/83901129ora-01000:maximumopencursorsexceeded:表示已经达到一个进程打开的最大游标数。1.主要原因:Java代码在执......
  • 练习题01
    1、编写程序将"jdk"全部变为大写,并输出到屏幕,截取子串"DK"并输出到屏幕2、写一个方法判断一个字符串是否对称3、编写一个程序,将下面的一段文本中的各个单词的字母顺......
  • LcdTools如何添加图片画面到PX01显示
    LcdTools打开点屏工程,切到“画面设置”栏,在“画面资源”栏选择“Picture”画面,先设置图片ID编号(此编号用于PG对图片编号,便于PG从SD卡中搜寻);  在“添加图......
  • 基于Ernie-3.0 CAIL2019法研杯要素识别多标签分类任务
    相关项目:​​Paddlenlp之UIE模型实战实体抽取任务【打车数据、快递单】​​​​Paddlenlp之UIE分类模型【以情感倾向分析新闻分类为例】含智能标注方案)​​​​应用实践:分类......
  • LcdTools如何自定义读写PX01 SSD2828寄存器
    LcdToos打开相应的工程文件,连接PX01并开启点亮屏使LcdTools开关处于开启状态。切到“测试设置”栏,在“Bridge控制”栏,在“Addr”处写需要操作的寄存器地址值(十六......
  • Solution Set -「NOIP Simu.」20221011
    「Unknown」找  给出平面上\(n\)个点,对于每个点,求出它到其他点的欧式距离平方和.  \(n\le2\times10^5\).  Tag:「水题无tag」  画风正常的签到题.\(d......