1.题目
http://acm.hdu.edu.cn/showproblem.php?pid=1114
2.分析
题目要求是装满,即在本价值限制LimitValue下减去本物品价值Value之后的LimitValue`必须存在一个已经计算出来的值。(如果采用初始化的值的话,就变成背包不要求装满,慢慢理解)。 因此,和完全背包的思路相似,则初始化的时候,要么初始化为整形最大值,计算的时候用state[i]=min(state[i],state[i-w]+p);要么初始化为整形最小值,计算的时候用判断state[i-w]是否不等于整形最小值(即是已经计算过值)。
动态规划方程:f[v]=max{f[v],f[v-cost]+weight}
3.复杂度
时间复杂度O(VN);空间复杂度O(V);
4.涉及内容
动态规划
5.感想
题目要求装满,因此是根据典型的完全背包变化而来。
关于背包初始化有两种情况:
1)背包不要求装满:初始化的时候,在任何一个价值限制下,0肯定都满足题目要求不装满,根据动态规划由前边导出后边值的时候0是一个满足条件的值。
2)背包要求装满:初始化的时候,在0价值限制下,0肯定满足要求装满;在非零价值线之下,由于是初始化,自然没有任何数值满足条件要求,因此可以初始化为整形最大值或者整形最小值,此时,在推导的时候都需要考虑上一次的价值是否是在装满条件下的(即不是整形最大值或者最小值,而是新计算出来的值)。判断的方法:当初始化为最小值的时候,用f[v]=max{f[v],f[v-cost]+weight};当初始化为最大值的时候,用f[v]=min{f[v],f[v-cost]+weight};或者用if判断f[v-cost]是否是初始化的值即可。
6.代码
#include <iostream>
using namespace std;
long state[10001];
void init()
{
state[0]=0;
for(int i=1;i<=10000;++i)
state[i]=25000001;
}
long min(long a,long b)
{
return a>b?b:a;
}
void CompletePack(int p,int w,int limitw)
{
for(int i=w;i<=limitw;++i)
{
state[i]=min(state[i],state[i-w]+p);
}
}
int main()
{
freopen("in.txt","r",stdin);
int T,E,F,N,P,W;
cin>>T;
while(T--)
{
init();
cin>>E>>F>>N;
while(N--)
{
cin>>P>>W;
CompletePack(P,W,F-E);
}
if(state[F-E]!=25000001)
cout<<"The minimum amount of money in the piggy-bank is "<<state[F-E]<<"."<<endl;
else
cout<<"This is impossible."<<endl;
}
return 0;
}
7.参考文献
《背包九讲》