01背包与贪心的区别
- 01背包问题是考虑整体最优解
- 贪心的前提是:局部最优解能产生全局最优解
例子:背包容量M,要求尽可能装入背包中的物品总价值最大
M: 30
重量:28 20 11
价值:28 21 11
如果用贪心算法,如果选取性价比最大的,即先选20,则后面就不可以再添加了,所以这里不能用贪心。如果物体可分割,则选取性价比策略的贪心是可以的。
描述
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。” 如果你是辰辰,你能完成这个任务吗?
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
思路
想法:前i件物品中,选取若干件放入背包中
状态:在前i件物品中,选取若干件放入剩余空间为j的的背包中所获得的最大值。
决策:第i件物品放还是不放
w[i]和v[i]分别为第i件物品的体积和价值。
F[i-1][j]表示前i-1件物品中选取若干件放入空间为j的背包中具有的最大价值。
- 如果F[i][j]中的i件物品选取的若干件物品中包含第i件物品,则F[i][j]=F[i-1][j-w[i]]+v[i],F[i-1][j-w[i]]为去除掉第i件的最大价值,再加上第i件的价值v[i].
- 如果F[i][j]中的i件物品选取的若干件物品中不包含第i件物品,则F[i][j]=F[i-1][j]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
int max(int a,int b)
{
return a>b?a:b;
}
struct bag
{
int w;//物体体积
int v;//物体价值
}b[105];
int dp[105][1005];
int main()
{
int T,M;
while(scanf("%d%d",&T,&M)!=EOF)
{
for(int i=1;i<=M;i++)
{
scanf("%d%d",&b[i].w,&b[i].v);
dp[i][0]=0;
}
for(int j=0;j<T;j++)
{
dp[0][j]=0;
}
for(int i=1;i<=M;i++)
{
//分两步
for(int j=T;j>=b[i].w;j--)//当j大于第i个物体的体积时,即背包可以放下物体i时
{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-b[i].w]+b[i].v);
}
for(int j=0;j<b[i].w;j++)//当背包放不下物体i时,则dp[i][j]只能从dp[i-1][j]转化而来
{
dp[i][j]=dp[i-1][j];
}
}
printf("%d\n",dp[M][T]);
}
return 0;
}