题目链接:
题目如下:
![](https://i-blog.csdnimg.cn/blog_migrate/3c1b88d8210b48534261ff8842c48cf9.png)
思路
这就是一道背包dp中最原始的01背包问题。
先介绍什么是dp(动态规划),动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
然后说一下什么转移方程,转移方程很简单就是:大问题=f(小问题)。
解一道dp题目最重要的是找到它的转移方程,一般转移方程写出来,问题就解决了。
简单介绍完之后,我们回到题目:
题目有两个变量:药的数量和可以采药的时间。然后我们把这两个变量一个一个细分,比如只采前i个药,有j时间的结果。然后我们就可以发现我们把一个问题给划分成M*T个问题,我们用一个二维数组来进行存储f[i][j],表示只采前i个药,有j时间的结果。
然后我们来找状态转移方程,首先这道题中药有两种状态:采和不采。如果我们要采摘药的话,会消耗采摘的时间(设为t),获得价值v,结果为f[i-1][j-t]+v,而不采药的话,结果为f[i-1][j],即上一个的结果,然后我们取两个之间的最大值,就是f[i][j]的结果。那么转移方程就出来了:
这道题也就结束了。我们开个二重循环遍历i和j,最后f[M][T]就是我们需要的答案。
代码采用一维数组:
#include <stdio.h>
int v[111];//价值
int r[111];//所需时间
int dp[1111];
int main() {
int i, j, T, M;
scanf("%d%d", &T, &M);
for (i = 1; i <= M; i++) {
scanf("%d%d", &r[i], &v[i]);
}
for (i = 1; i <= M; i++) {
for (j = T; j >= 1; j--) {
if (j >= r[i])
dp[j] = (dp[j] > dp[j - r[i]] + v[i]) ? dp[j] : (dp[j - r[i]] + v[i]);
}
}
printf("%d", dp[T]);
}