题目:acm.hdu.edu.cn/showproblem.php?pid=1114
这个题的关键在于“背包”是恰好完全装满的,所以涉及到一个小技巧:初始化将dp[1...v]设为负无穷,dp[0]设为0,最后dp[v]即所求。
好吧,其实这个技巧在我看《背包九讲》的时候已经看见了_(:з」∠)_,但是操作起来还是有点困难。
首先,这个题要求的是背包恰好完全装满时做少的钱,(o(╥﹏╥)o一般背包问题都求最大的“价值”,所以用到无穷小)所以要设为无穷大啊!!!
总结:
①
求最大值,dp数组除dp[0]=0外初始化为无穷小 #define Min 0xc0c0c0c0 最后特判if (dp[v]>0)
求最小值,dp数组除dp[0]=0外初始化为无穷大 #define Max 0x3f3f3f3f 最后特判if (dp[v]!=Max)
PS:此时初始化不能用memset (dp,Min,sizeof(dp)) !!!因为memset初始化只对0,-1有用
(不知道为啥在网上看了那么多不是0,-1也用memset初始化的_(:з」∠)_,反正我dev编译有问题→_→)
②
如果runtime error,再看一遍题,是不是数组开小了
(这道题我一开始没想清楚,dp[505]结果wa了好久看不出来o(╥﹏╥)o,蠢爆了ヾ( ̄▽ ̄)Bye~Bye~)
代码:
#include <bits/stdc++.h>
using namespace std;
#define Max 0x3f3f3f3f //无穷大
int main()
{
int t,n;
int p[505],w[505]; //price,weight
int dp[10005]; //钱罐中的钱
cin>>t;
while (t--)
{
int before,after,v;
cin>>before>>after;
v=after-before;
cin>>n;
for (int i=0;i<10005;i++)
{
dp[i]=Max;
}
dp[0]=0;
for (int i=1;i<=n;i++)
{
cin>>p[i]>>w[i];
}
for (int i=1;i<=n;i++)
{
for (int j=w[i];j<=v;j++)
{
dp[j]=min(dp[j],dp[j-w[i]]+p[i]);
}
}
if (dp[v]!=Max) cout<<"The minimum amount of money in the piggy-bank is "<<dp[v]<<"."<<endl;
else cout<<"This is impossible."<<endl;
}
return 0;
}