【01背包】HDU2602-Bone Collcetor POJ3624-Charm Bracelet(模板)

2023-12-15 22:39

本文主要是介绍【01背包】HDU2602-Bone Collcetor POJ3624-Charm Bracelet(模板),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天迟到了QAQ在众人众目睽睽之下走到最后一排的感觉跟走在红地毯上的感觉是一样一样的


上星期学长讲DP的时候就想看看背包了,结果刷了一星期的LCS整个人都不好了,今天老师正好又说到了这个,赶紧补一补,这是模板题啊,注意了!

先把01背包介绍一下,老师发给的资料还真浅显易懂!

以下引用老师发的资料,有增删:

01背包(ZeroOnePack

      有N件物品和一个容量为V的背包, 每种物品均只有一件。第i件物品的费用是c[i],价值是w[i]。那么应该怎样挑选,才能将哪些物品装入背包可使总价值最高? 

 0-1背包

      0-1背包是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。

      用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:

f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}

 

      这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:

   “将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。

      在前i件物品放进容量v的背包时,它有两种情况:

f[i-1][v]:如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];

f[i-1][v-c[i]]+w[i]:如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。

      最后比较第一种与第二种所得价值的大小,哪种相对大,f[i][v]的值就是哪种(这里是重点,理解!)。  

      有了状态转移方程,那么写起代码来就非常简单了,首先看一下自顶向下的递归方式,比较容易理解。

实例分析

题目描述:

      有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?

name

  weight

  value

  1

  2

  3

  4

  5

  6

  7

8

9

10

a

2

6

0

6

6

9

9

  12

  12

  15

  15

  15

b

2

3

0

3

3

6

6

9

9

9

10

11

c

6

5

0

0

0

6

6

6

6

6

10

11

d

5

4

0

0

0

6

6

6

6

6

10

10

e

4

6

0

0

0

6

6

6

6

6

6

6

 

      只要你能通过找规律手工填写出上面这张表就算理解了01背包的动态规划算法。

      首先要明确这张表是自底向上,从左到右生成的。

      为了叙述方便,用e2单元格表示e行2列的单元格,这个单元格的意义是用来表示只有物品e时,有个承重为2的背包,那么这个背包的最大价值是0,因为e物品的重量是4,背包装不了。

对于d2单元格,表示只有物品e,d时,承重为2的背包,所能装入的最大价值,仍然是0,因为物品e,d都不是这个背包能装的。

同理,c2=0,b2=3,a2=6。

      对于承重为8的背包,a8=15,是怎么得出的呢?

      根据01背包的状态转换方程,需要考察两个值,

      一个是f[i-1,j],对于这个例子来说就是b8的值9,另一个是f[i-1,j-Wi]+Pi;

      f[i-1,j]表示我有一个承重为8的背包,当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值。

      f[i-1,j-Wi]表示我有一个承重为6的背包(等于当前背包承重减去物品a的重量),当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值f[i-1,j-Wi]。就是指单元格b6,值为9,Pi指的是a物品的价值,即6。

      由于f[i-1,j-Wi]+Pi = 9 + 6= 15 大于f[i-1,j] = 9,所以物品a应该放入承重为8的背包。


      可能看到这里很多人都理解了01背包的大致原理,DP嘛,当然是从后往前推的。但是,当时我死活不理解那个动态规划的方程是啥意思,后来吃饭的时候终于想通了他是这样的:

                                                          f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}

      这个式子中要比较的第一个元素f[i-1][v]很显然是在此背包空间下,如果不装当前物品,背包中所含物品的最大价值总和;那么后面那一个呢?自然是如果装当前物品背包中所含的总价值。那么,要想装下当前物品,需要背包有充足的余量空间才行,而f[i-1][v-c[i]]所表达的,就是当前背包中,如果去掉c[i]空间的物品,背包中剩下的物品的总价值!而此值经过前面的计算,恰恰就是当去掉c[i]空间物品(此时当然不用考虑到底去掉了谁,因为dp所储存的值永远是符合题意的最大值)时的最大值!此时因为已经去掉了c[i]空间的物品,当前物品一定能装进背包中,因此此时背包总价值为f[i-1][v-c[i]]+w[i],用这个跟前面那个比较取最大的,当然就是当前背包能装物品的最大价值咯,还是比较好想的,反正我是这么理解的,如果有错还请大家在下面留言指正哦!

【题目】


Bone Collector

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description
Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave …
The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ?


Input
The first line contain a integer T , the number of cases.
Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.

Output
One integer per line representing the maximum of the total value (this number will be less than 2 31).

Sample Input
  
1 5 10 1 2 3 4 5 5 4 3 2 1

Sample Output
  
14

【题意】

      就是说一个人很喜欢收集骨头,现在给你一些骨头的参数(占用空间、骨头价值),问背包里能装下的最大骨头的最大价值是多少

      输入:第一行是实例数,第二行第一个是有几根骨头,第二个数是背包容量。下面两行,第一行代表骨头价值,第二行指所占每个骨头空间。

      输出:输出背包所能装下骨头的最大价值。


【思路】

      上面对01背包解释地非常清楚了,由于上面的介绍是用表格的方式,这里我写的是用的二维数组的方法。二维数组适用于骨头数目不多的情况。用V储存动态规划时每种情况的最大价值,b表示所占空间,a表示每根骨头的价值。输入完成后先将V置0,不然可能影响下次实例计算。上面介绍的方向是从左往右,从下向上,而我们的代码要反过来一下,从上到下,运算先后问题而已,不过不影响结果。先把V第一行符合空间的第一个骨头放入背包,接着进入主循环,第一个循环将当前的值设置为“f[i-1][v]”,然后第二个分循环将这个值与如果放入当前骨头的价值的值作比较取大者,就是当前背包的最大价值了,这里注意不要让这个表格从(1,1)开始走,我一开始这样写提交了结果听取WA声一片。直接让V第一行储存如果能装入第一根骨头时的价值。最后V[n-1][v]就是要求的最大值了

【代码】

#include<stdio.h>
#include<string.h>
#define MAX(x,y) x>y?x:y
int V[1005][1005],a[1005],b[1005];//a是价值,b是体积 int main()
{int t;scanf("%d",&t);while(t--){memset(V,0,sizeof(V));int n,v;scanf("%d%d",&n,&v);for(int i=0;i<n;i++)scanf("%d",&a[i]);for(int i=0;i<n;i++)scanf("%d",&b[i]);for(int i=b[0];i<=v;i++)//先把V[0][i]能装进第一根骨头的全装入第一根骨头 V[0][i]=a[0];for(int i=1;i<n;i++)//此时i从1开始,因为后面有i-1的情况。 编辑此二维数组时,千万不要让第一个元素下标是V[1][1],我也不造为啥但是那样写会WA {for(int j=0;j<b[i];j++)V[i][j]=V[i-1][j];for(int j=b[i];j<=v;j++)V[i][j]=MAX(V[i-1][j],V[i-1][j-b[i]]+a[i]);}printf("%d\n",V[n-1][v]);}return 0;
}


好好理解一下,下面贴POJ的题~

【题目】

Charm Bracelet
Time Limit: 1000MS Memory Limit: 65536K
   

Description

Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi≤ 400), a 'desirability' factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).

Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.

Input

* Line 1: Two space-separated integers:  N and  M
* Lines 2.. N+1: Line  i+1 describes charm  i with two space-separated integers:  Wi and  Di

Output

* Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints

Sample Input

 
4 6
1 4
3 12
2 6
2 7

Sample Output

23

【题意】
      我就不讲故事了,01背包裸题
      输入:第一行第一个数是n,第二个是背包容量
               下面n行第一个数是空间,第二个是价值
      输出:最大价值,占一行

【思路】
      这个跟上面一样,可恶的是用二维数组会炸,我们这次不用二维数组,如果能看懂上面那道题,不用二维数组也很简单,是一样的想法。 将当前不放新物品的价值与放新物品的价值比较取大者,记录价值的一位数组不断被更新 ,最后输出此数组最后一个元素就是答案了!

【代码】

#include<cstdio>
#include<cstring>
#define MAX(X,Y) X>Y?X:Y
int dp[13000],w[13000],d[13000];int main()
{int n,m;while(scanf("%d%d",&n,&m)!=EOF){for(int i=1;i<=n;i++)scanf("%d%d",w+i,d+i);memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++){//与二维数组不一样的是,这里被必要把前面那一个价值赋给当前背包,直接比较更新就好了! for(int j=m;j>=w[i];j--)dp[j]=MAX(dp[j],dp[j-w[i]]+d[i]);}printf("%d\n",dp[m]);}return 0;
}

两种方法搞了一天啊啊啊啊啊要疯了!

这篇关于【01背包】HDU2602-Bone Collcetor POJ3624-Charm Bracelet(模板)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/498162

相关文章

C++的模板(八):子系统

平常所见的大部分模板代码,模板所传的参数类型,到了模板里面,或实例化为对象,或嵌入模板内部结构中,或在模板内又派生了子类。不管怎样,最终他们在模板内,直接或间接,都实例化成对象了。 但这不是唯一的用法。试想一下。如果在模板内限制调用参数类型的构造函数会发生什么?参数类的对象在模板内无法构造。他们只能从模板的成员函数传入。模板不保存这些对象或者只保存他们的指针。因为构造函数被分离,这些指针在模板外

C++入门01

1、.h和.cpp 源文件 (.cpp)源文件是C++程序的实际实现代码文件,其中包含了具体的函数和类的定义、实现以及其他相关的代码。主要特点如下:实现代码: 源文件中包含了函数、类的具体实现代码,用于实现程序的功能。编译单元: 源文件通常是一个编译单元,即单独编译的基本单位。每个源文件都会经过编译器的处理,生成对应的目标文件。包含头文件: 源文件可以通过#include指令引入头文件,以使

记录AS混淆代码模板

开启混淆得先在build.gradle文件中把 minifyEnabled false改成true,以及shrinkResources true//去除无用的resource文件 这些是写在proguard-rules.pro文件内的 指定代码的压缩级别 -optimizationpasses 5 包明不混合大小写 -dontusemixedcaseclassnames 不去忽略非公共

C++标准模板库STL介绍

STL的六大组成部分 STL(Standard Template Library)是 C++ 标准库中的一个重要组成部分,提供了丰富的通用数据结构和算法,使得 C++ 编程变得更加高效和方便。STL 包括了 6 大类组件,分别是算法(Algorithm)、容器(Container)、空间分配器(Allocator)、迭代器(Iterator)、函数对象(Functor)、适配器(Adapter)

HTML5文旅文化旅游网站模板源码

文章目录 1.设计来源文旅宣传1.1 登录界面演示1.2 注册界面演示1.3 首页界面演示1.4 文旅之行界面演示1.5 文旅之行文章内容界面演示1.6 关于我们界面演示1.7 文旅博客界面演示1.8 文旅博客文章内容界面演示1.9 联系我们界面演示 2.效果和源码2.1 动态效果2.2 源代码2.3 源码目录 源码下载万套模板,程序开发,在线开发,在线沟通 作者:xcLeigh

407串口01发送

实验一: 工程。 链接:https://pan.baidu.com/s/1g8DV4yZWOix0BbcZ08LYDQ?pwd=2176 提取码:2176 串口1的使用。发送功能。 单片机发送信息到电脑。 通过串口进行通信。 首先单片机这边。 单片机这边,需要对单片机的串口模块进行使能初始化,设置串口的格式。 单片机和电脑的串口收发格式要配置一致。不然A和B肯定通信不成功,鸡和鸭讲,

静态文件及模板

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm=1001.2014.3001.5501 1  静态文件 动态Web应用也会需要静态文件,通常是CSS和JavaScript文件。Flask可以向已经配置好的Web服务器提供静态文件,只要在包或模块所在的目录中创建一个名为s

周末设计高端企业_集团官网主题Discuz模板

风格名称: 周末设计_高端企业_集团官网 适用版本: Discuz! X3.0、X3.1、X3.2、X3.3、F1.0 风格编码: 使用语言包结构,适合全部编码 周末设计高端企业_集团官网主题Discuz模板

秋招突击——6/22——复习{区间DP——加分二叉树,背包问题——买书}——新作{移除元素、实现strStr()}

文章目录 引言复习区间DP——加分二叉树个人实现 背包问题——买书个人实现参考实现 新作移除元素个人实现参考思路 找出字符串中第一个匹配项的下标个人实现参考实现 总结 引言 今天做了一个噩梦,然后流了一身汗,然后没起来,九点多才起床背书。十点钟才开始把昨天那道题题目过一遍,然后十一点才开始复习题目,为了不耽误下午的时间,所以这里的就单纯做已经做过的题目,主打一个有量,不在学

大学生自救数据结构与算法(py实现)——01递归

目录 目录 递归 基本概念 工作原理 基本要素 优点 缺点 实现技巧 实例解析:计算阶乘 斐波那契数列 高效的斐波那契数列 python中的最大递归深度 二分查找 基本原理 性能分析 优化与变体 线性递归  元素序列的递归求和 二路递归 二路递归的基本概念 典型应用 工作原理 多重递归  示例:计算卡特兰数(Catalan Number) 尾递