时间限制:1 秒
内存限制:32 兆
特殊判题:否
提交:4706
解决:2358
-
题目描述:
-
辰辰是个很有潜能、天资聪颖的孩子,他的梦想是称为世界上最伟大的医师。
为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。
医师把他带到个到处都是草药的山洞里对他说:
“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。
我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
-
输入:
-
输入的第一行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),T代表总共能够用来采药的时间,M代表山洞里的草药的数目。
接下来的M行每行包括两个在1到100之间(包括1和100)的的整数,分别表示采摘某株草药的时间和这株草药的价值。
-
输出:
-
可能有多组测试数据,对于每组数据,
输出只包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
-
样例输入:
-
70 3 71 100 69 1 1 2
-
样例输出:
-
3
***********************************************
这是一道0-1背包问题。刚开始我也想用贪心做,发现不行,上网搜了别人的经验,得出结论是贪心不能保证背包空间的充分利用,导致单位空间的价值降低,它可以解决部分背包问题,但不可以解决0-1背包问题。这也恰恰体现了0-1背包问题的特点:物品在背包里只有两种可能的状态,有或无。所以这个问题就可以理解成不断的判断每个物品是否应该留在背包里的问题,这是个动态的过程,适合用动态规划的方法解决。即考虑:选择前i个物品时,所需空间不超过j时所能达到的最大重量。初始状态dp[i][j]全部置成0.若求“选择前i个物品时,所需空间恰好为j时所能达到的最大重量”,则除了dp[0][0]=0外,其余dp[0][j]全部为负无穷。还有,空间复杂度可以进一步降低,即二维数组可以转化为一维数组,这是由于状态转移时本行只与上一行有关。下面给出简化之后的代码:
#include <cstdio>
#include <algorithm>
using namespace std;
struct drug{
int time;
int value;
};
drug buf[101];
int dp[1001];
int main()
{
int t,m;
while(scanf("%d%d",&t,&m)!=EOF){
for(int i=1;i<=m;i++){
scanf("%d%d",&buf[i].time,&buf[i].value);
}
for(int i=0;i<=t;i++){
dp[i]=0;
} //初始化
for(int i=1;i<=m;i++){
for(int j=t;j>=buf[i].time;j--){
dp[j]=max(dp[j],dp[j-buf[i].time]+buf[i].value); //dp[j]在原值和保留第i个物品
} //两者之中取最大的
}
printf("%d\n",dp[t]);
}
return 0;
}