C++ 0/1背包(比数字三角形难1/inf左右的DP)

博客围绕洛谷P1048采药问题展开,介绍了C++语言下的解题思路。先给出题面,包括题目描述、输入输出格式等,接着分析题解,提及骗分、暴搜、贪心等方法,重点阐述了动态规划解法,给出状态转移方程,还进行了优化,最后给出最终代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门:P1048 [NOIP2005 普及组] 采药 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

如果你还没有学过DP的话,推荐你看一下我的这一篇博客:

(14条消息) C++ 数字三角形(最最最基础的DP)_jinjiayang的博客-CSDN博客

题面

如果你不愿点击传送门的话,这是题目

题目描述

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

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

输入格式

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

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

输出格式

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

输入输出样例

输入 #1

70 3
71 100
69 1
1 2

输出 #1

3

说明/提示

【数据范围】

  • 对于 30% 的数据,M≤10;
  • 对于全部的数据,M≤100。

【题目来源】

NOIP 2005 普及组第三题
 

题解

下面我们将要分析一道十分著名的题目:0/1DP

下面请选择你读完题的感受:
A骗分 B暴力搜索 C贪心 D动规

骗分

不说了。。。

暴搜

搜你搜到天荒地老。。。

贪心

看过(14条消息) C++ 数字三角形(最最最基础的DP)_jinjiayang的博客-CSDN博客

的人明显知道不对,没看过的去看一遍也知道怎么不对了

正解:动规

很明显,该题显然满足最优子结构和无后效性原理,满足DP的先决条件

状态转移方程

DP[i][j] = MAX(DP[i-1][j-W[i]] + V[i], DP[i-1][j])
DP:存储最优解的数组
V:草药的价值
W:采摘草药的时间
i:还剩下i株草药采摘
j:在当前剩下i株草药可采摘的情况下,还剩余j时间

翻译成人类语就是:

还剩下i株草药j时间的最优解(dpij)是还剩下i-1株草药j时间减去当前草药时间加上当前草药价值的解(dpi-1j-wi+vi)和还剩下i-1株草药j时间(dpi-1j)的解的最大值(max)

答案输出

很明显,是max(dp[m][c])

优化

根据状态转移方程可知,dp[x][]的值肯定是从dp[x-1][]的值推导过来的,那么在数组中存储剩余几株草药这个量是没有意义的,可使空间复杂度由n^2降为n,从平方降到线性

最终代码

#include<bits/stdc++.h>
using namespace std;


int wgt[1002], vls[1002], dp[1002];

int main()
{
	int n, c;
	cin >> c >> n;
	for(int i=1; i<=n; i++) cin >> wgt[i] >> vls[i];
	for(int i=1; i<=n; i++) for(int j=c; j>=wgt[i]; j--)
	{
		dp[j] = max(dp[j-wgt[i]] + vls[i], dp[j]);
	 } 
	cout << dp[c];
}

time to 点赞

看完后,别忘了

点赞!

收藏!

Thanks……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘉定世外的JinJiayang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值