洛谷 P1048 [NOIP2005 普及组] 采药

这篇博客介绍了如何解决NOIP2005普及组的采药问题,该问题是一个典型的动态规划中的01背包问题。文章详细阐述了01背包问题的概念,给出了输入输出样例,并解析了状态转移方程,最后提供了相应的代码实现。

典型的动态规划中的01背包问题

何为01背包问题

01背包问题:每件物品是不可以被分割的,也就是说,这件物品要么装进背包内带走,要么不带走。0表示该物品没有被带走(没有被装进背包内),1表示带走该物品。


输入输出样例及说明

输入

70 3
71 100
69 1
1 2

输出

3
由于采每株草药的时间是不可以被分割的,只能选择采或不采。这里选择第二株草药和第三株草药带走。(花费时间)为69+1=70,未超过背包容量(总时间),价值是:1+2=3

状态转移方程

状态

f(i,j)表示前i株草药,在剩余时间为j时能获得的最大价值。

状态转移方程

状态转移方程

此处分两种情况:

①前i-1株草药在剩余时间为j时可以获得最大值,即不采第i株草药;
②前i-1株草药在剩余时间为j-w[i]时获得最大价值 + 第i株草药价值v[i],即采第i株草药

代码

#include<bits/stdc++.h>//万能头
using namespace std;
const 
### 平台上的经典背包问题题目列表 平台上提供了多种经典的背包问题编程题目,涵盖了 **01 背包**、**完全背包** 和 **多重背包** 等类型,适合不同层次的学习者进行练习。以下是一些具有代表性的题目列表及简要说明: --- #### 01 背包问题 - **P1048 [NOIP2005 普及组] 采药** 给定一个固定容量的背包和若干种草药,每种草药只能采集一次,要求在限定时间内获得最大价值。该题是典型的 01 背包模型,适合初学者练习基础动态规划思想[^5]。 - **P1060 [NOIP2006 提高组] 开心的金明** 在预算范围内选择商品,每种商品只能选一次,目标是使总价值最大化。该题使用标准的 01 背包状态转移方程进行求解。 --- #### 完全背包问题 - **P1616 疯狂的采药** 该题与普通完全背包问题类似,每种物品可以无限次选取,要求在限定容量下最大化总价值。题目中使用一维数组优化空间,并采用正向遍历更新状态[^1]。 - **P1216 [USACO1.5] [IOI1994]数字三角形 Number Triangles** 虽然不是传统背包问题,但其动态规划思想与完全背包类似,适合训练状态转移的设计。 --- #### 多重背包问题 - **P1775 石子合并(动态规划)** 该题虽然不是典型的多重背包,但其动态规划状态转移方程设计较为复杂,适合进阶学习者练习状态转移的优化技巧。 - **P5365 [SNOI2019]舞蹈** 该题涉及多重选择问题,可以通过二进制优化的方法转化为多个 01 背包问题进行求解,是多重背包的典型应用之一。 --- #### 混合背包问题 - **P1838 健美操(动态规划)** 题目中物品的选取方式包括 01、完全和多重三种情况,要求根据不同的选取方式分别处理,是混合背包问题的经典题目。 --- #### 变形背包问题 - **P2347 砝码称重** 该题使用背包思想判断是否能称出某个重量,属于“可行性背包”问题,通过布尔型动态规划数组记录状态。 - **P2051 [AHOI2009] 中国象棋** 该题属于“组合型背包”问题,要求在棋盘上放置炮兵,使得每行每列不超过两个,通过状态压缩与背包思想结合求解。 --- ### 示例代码(完全背包) 以下是一个典型的完全背包问题的 C++ 实现,用于求解最小花费问题: ```cpp #include <bits/stdc++.h> using namespace std; #define int long long int n, h; int w[105]; int v[105]; int dp[55005]; // 因为最多一袋50000斤再额外加袋的重量 signed main() { cin >> n >> h; for (int i = 1; i <= n; i++) { cin >> w[i] >> v[i]; } for (int i = 1; i <= h + 5005; i++) { dp[i] = 0x3f3f3f; } for (int i = 1; i <= n; i++) { for (int j = w[i]; j <= h + 5005; j++) { dp[j] = min(dp[j], dp[j - w[i]] + v[i]); } } int ans = 0x3f3f3f3f; for (int i = h; i <= h + 5005; i++) { ans = min(ans, dp[i]); } printf("%lld", ans); return 0; } ``` --- ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值