-题目来源:
![]()
题目描述:
描述
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。” 如果你是辰辰,你能完成这个任务吗?
输入格式
输入文件medic.in的第一行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
输出格式
输出文件medic.out包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
测试样例1
输入
70 3 71 100 69 1 1 2
输出
3
备注
对于30%的数据,M <= 10;对于全部的数据,M <= 100。
-------------------------------------------------------------------------------------------------------------------------------------
思路:这个问题属于背包问题,更进一步讲是0-1问题。
一开始我尝试使用价值/时间最大法,即将所有药材都以 价值/时间 降序排列,从 价值/时间 最大的开始塞进背包直到超出时间。这种方法的确能够通过样例,但是这个样例实在太简单了,没有暴露出其他问题,所以没有AC,于是将原题目百度了一下,发现要使用动态规划的方法。(可见:http://wenku.baidu.com/link?url=SDqMRJ5bPrTPn3P-Nx3dpao2nVqvPiiBghk8qd5CMtDVFp5CWdOSBkrKgpHdStWB7vHPFSU_o3qSBknCh_boul2TXH1vT8ZJhsAy2roEUtq)
关键的动态规划要点我总结如下:
1、把所有的草药从上到下排成1列,从1开始升序编号。
2、采药的终极目标是使到最后的价值最大,那么我们可以求对每一株的最大价值来获得最后的最大价值。
3、两个重要推论:(来自分析和解答)
4、
若wj>Y,则A(j,Y)=A(j-1,Y)。也就是说,如果采这药材的时间超过最长时间,那么到这个药材的最大价值等于前一个药材的最大价值。
若
Y
w
j
>
,
则
)
,
1
(
)
,
(
Y
j
A
Y
j
A
−
=
。
5、若wj<Y,则A(j,Y)=max(A(j-1,Y),A(j-1,Y-wj)+pj).
这就是说,如果采这个药材的时间没有超过最长时间,那么这株药材的最大价值时间就是前一个药材并且在Y减去该药材所需时间后的局限时间里的最大价值。
6、开二维数组 int Gather[M+1][T+1],Gather[i][j]的值表示总的采药时间不超过j,采药数量不超过i时所采草药的最大价值。
然后以下图的顺序开始遍历
_______________________________________________________________________________________________________________________________________________________
知道思路之后,会遇到一些代码编写上的小问题。(我用的是C)
要注意到Gather二维数组的是以[数量][时间]为坐标的,这和输入数据不同,容易搞混;
其次,Gather二维数组的标度比真正的标度要大1,所以Array数组中会出现i-1的情况。
AC代码如下:
#include <stdio h=""></stdio>
#include <stdio h="">
<pre name="code" class="cpp">#include <stdlib.h>
void Package(int T,int M);
int Max(int A,int B);
int Array[100][2];
int Gather[101][1001];
int main()
{
int M,T;
int Time, Result;
int i;
scanf("%d%d",&T,&M);
for(i = 0;i < M;i++)
{
scanf("%d%d",&Array[i][0],&Array[i][1]);
}
Time=0;
Result=0;
Package(T,M);
printf("%d\n",Gather[M][T]);
//system("pause");
return 0;
}
void Package(int T,int M)
{
int i,j;
int a,b;
for(i=0;i<T+1;i++)
Gather[0][i]=0;
for(i=0;i<M+1;i++)
Gather[i][0]=0;
for(i = 1;i < T+1;i++)
for(j = 1;j < M+1;j++)
{
if(Array[j-1][0]>i)
Gather[j][i]=Gather[j-1][i];
else
{
Gather[j][i]=Max(Gather[j-1][i],Gather[j-1][i-Array[j-1][0]]+Array[j-1][1]);
}
/*for(a = 0; a < M+1; a++)
{
for(b = 0; b <T+1;b++)
printf("%2d",Gather[a][b]);
printf("\n");
}
printf("__________________________\n");
*/
}
}
int Max(int A,int B)
{
return (A>B)?A:B;
}