DP入门之采药问题

                                     想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
                                     转载请注明出处:
http://blog.csdn.net/wangjian8006

采药
              输入第一行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
              关于输出
              输出包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
              例子输入
                  70 3
                  71 100
                  69 1
                  1 2
              例子输出
                  3

我们用maxvalue[i][j]表示,在前i个物品中在j分钟的最大值,那么其实对于一个物品,它有取这个物品和不取这个物品两种状态

假设共有m个物品,总时间是t,times[i]表示第i个物品需要多少时间,values[i]表示第i个物品的价值,且从1开始

拿一个例子来分析

10 3

10 1

5 4

3 3

初始化maxvalue全部为0,那么结果应该是这样:

012345678910
000000000000
1(10,1)00000000001
2(5,4)00000444444
3(3,3)00033444777


 

 

如果只有草药1可选,则花掉全部10分钟,最大值是1
如果还有草药2可选,时间也只够在1,2中选其一,采草药2剩余的时间,也不够采草药1,但是选2比较划算,最大值是4
如果还有草药3可选,在第1‾4分钟,只够采草药3,三种草药之和还是3。
第5--7分钟有可采2和3两种选择,显然,采草药2更划算,选择不采3,最大值是4
到了第8分钟,时间够采2,3,
则最大值是两者价值之和7

 

根据上面,当对于i,取i的话,应该是maxvalue[i][j]=maxvalue[i-1][j-times[i]]+value[i]

那么因为取了i,所以在前i-1个药品中的前j-times[i]分钟的最大分钟再加上i的价值,因为选了i,所以前i-1个药品的时间应该要减去times[i]

如果不取i的话,那么maxvalue[i][j]=maxvalue[i-1][j]前j分钟取i个的最大值应该和前j分钟取前i-1的最大值相等


如果要确定maxvalue[i][j]的最大值,那么

maxvalue[i][j] = max(maxvalue[i-1][j],maxvalue[i-1][j-times[i]]+values[i]);

当然,前提条件是j>=times[i],否则就是时间不够,不能采这个药品


代码如下:

#include <iostream>
using namespace std;
#define MAXM 100
#define MAXT 1000
int max(int a,int b){return a>b?a:b;}

int times[MAXM],values[MAXM],maxvalue[MAXM][MAXT];

int main(){
	int t,m,i,j;

	while(scanf("%d%d",&t,&m)!=EOF){
		for(i=1;i<=m;i++)
			scanf("%d%d",×[i],&values[i]);
		
		memset(maxvalue,0,sizeof(maxvalue));
		for(i=1;i<=m;i++)
			for(j=0;j<=t;j++)
				if(j>=times[i])
					maxvalue[i][j] = max(maxvalue[i-1][j],maxvalue[i-1][j-times[i]]+values[i]);

		printf("%d\n",maxvalue[m][t]);
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值