采药 (动态规划)

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

如果你是辰辰,你能完成这个任务吗?
Input
输入的第一行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),T代表
总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括
两个在1到100之间(包括1和100)的的整数,分别表示采摘某株草药的时间和
这株草药的价值。

Output
输出只包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。

Sample Input
70 3
71 100
69 1
1 2

Sample Output
3

这道题我在做的时候很崩溃,因为一直WA, 最后不得不在网上寻找大佬的代码借鉴,动态规划的关系式一直想不到,不过这种算法在理解上还要多下功夫!!!

三步走

首先我们定义二维数组dp[i][j]为在拥有j长度时间时采集第i种草药所能获得的最大价值

其次我们寻找数组元素之间的关系式,我们知道,面对一种草药,我们的选择只有两种,

或者 不采 , 

  • 那么如果我们选择采的话,我们的dp[ i ][ j ]便于dp[ i -1 ][ j -a[l][1] ] 产生了关系

因为现在的状态就变成了上一个状态(消耗时间后)的最大价值加上我们所获得的草药价值

  • 反之如果我们不采,那么我们的dp[ i ][ j ]与上一个状态保持一致不变即可

最后是初始化,我们将dp数组初始化为0即可,因为没有采集草药即价值为0


int max(int a,int b)
{
	if(a>b)
	return a;
	else
	return b;
}

#include<stdio.h>
int t,n;
int a[10500][2];
int dp[10500][10500];定义二维数组dp[i][j]为在拥有j长度时间时采集第i种草药所能获得的最大价值
int main()
{
	int i,l,y;
    scanf("%d%d",&t,&n);
    for( i=1;i<=n;i++)
    scanf("%d%d",&a[i][1],&a[i][2]); 输入草药信息   
    for( l=1;l<=n;l++)
        for( y=t;y>0;y--)
        {
            if(a[l][1]<=y)//该种草药所需时间小于等于我们拥有的时间
            {
                dp[l][y]=max(dp[l-1][y],dp[l-1][y-a[l][1]]+a[l][2]);//看 采 或者 不采 该草药的价值对比
            }
            else dp[l][y]=dp[l-1][y];//该种草药所需时间大于我们拥有的时间(此时状态与上一个状态保持相同)
        }
    printf("%d",dp[n][t]);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZZZWWWFFF_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值