HDU 1114 Piggy-Bank (完全背包的应用)

题意

在 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;
        else
            cout<<"This is impossible."<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37685156/article/details/81138783
今日推荐