传送门: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……