题意
在 ACM 能够开展之前,必须准备预算,并获得必要的财力支持。该活动的主要收入来自于 Irreversibly Bound Money (IBM)。思路很简单。任何时候,某位 ACM 会员有少量的钱时,他将所有的硬币投入到小猪储钱罐中。这个过程不可逆,因为只有把小猪储钱罐打碎才能取出硬币。在足够长的时间之后,小猪储钱罐中有了足够的现金,用于支付 ACM 活动所需的花费。
但是,小猪储钱罐存在一个大的问题,即无法确定其中有多少钱。因此,我们可能在打碎小猪储钱罐之后,发现里面的钱不够。显然,我们希望避免这种不愉快的情况。唯一的可能是,称一下小猪储钱罐的重量,并尝试猜测里面的有多少硬币。假定我们能够精确判断小猪储钱罐的重量,并且我们也知道给定币种的所有硬币的重量。那么,我们可以保证小猪储钱罐中最少有多少钱。
你的任务是找出最差的情形,即判断小猪储钱罐中的硬币最少有多少钱。我们需要你的帮助。不能再贸然打碎小猪储钱罐了!
解题
完全背包问题。
设dp[i]表示背包容量为i时恰放满钱币的最小价值。
状态转移方程:
dp[i]=min{dp[i],dp[i-w[j]]+p[j]},j表示第j种钱币。
w[j]表示第j种钱币的重量,p[j]表示第j种钱币的价值。
初始化将dp的值都置为无穷大,最后经dp后,判断dp[F-E]的值是否为无穷大即可。
AC代码
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;const int maxn=1e4+7;
const int maxm=500+7;
int dp[maxn],p[maxm],w[maxm];int main()
{int T;cin>>T;while(T--){int E,F;cin>>E>>F;int N;cin>>N;for(int i=1;i<=N;i++)cin>>p[i]>>w[i];int W=F-E;memset(dp,0x3f,sizeof(dp));dp[0]=0;for(int i=1;i<=W;i++){for(int j=1;j<=N;j++){if(w[j]>i) continue;dp[i]=min(dp[i],dp[i-w[j]]+p[j]);}}if(dp[W]!=INF)cout<<"The minimum amount of money in the piggy-bank is "<<dp[W]<<"."<<endl;elsecout<<"This is impossible."<<endl;}
}