HDU-1114 Piggy-Bank

中文大意
在 ACM 能够开展之前,必须准备预算,并获得必要的财力支持。该活动的主要收入来自于 Irreversibly Bound Money (IBM)。思路很简单。任何时候,某位 ACM 会员有少量的钱时,他将所有的硬币投入到小猪储钱罐中。这个过程不可逆,因为只有把小猪储钱罐打碎才能取出硬币。在足够长的时间之后,小猪储钱罐中有了足够的现金,用于支付 ACM 活动所需的花费。

但是,小猪储钱罐存在一个大的问题,即无法确定其中有多少钱。因此,我们可能在打碎小猪储钱罐之后,发现里面的钱不够。显然,我们希望避免这种不愉快的情况。唯一的可能是,称一下小猪储钱罐的重量,并尝试猜测里面的有多少硬币。假定我们能够精确判断小猪储钱罐的重量,并且我们也知道给定币种的所有硬币的重量。那么,我们可以保证小猪储钱罐中最少有多少钱。

你的任务是找出最差的情形,即判断小猪储钱罐中的硬币最少有多少钱。我们需要你的帮助。不能再贸然打碎小猪储钱罐了!

输入
输入包含 T 组测试数据。输入文件的第一行,给出了 T 的值。

对于每组测试数据,第一行包含 E 和 F 两个整数,它们表示空的小猪储钱罐的重量,以及装有硬币的小猪储钱罐的重量。两个重量的计量单位都是 g (克)。小猪储钱罐的重量不会超过 10 kg (千克),即 1 <= E <= F <= 10000 。每组测试数据的第二行,有一个整数 N (1 <= N <= 500),提供了给定币种的不同硬币有多少种。接下来的 N 行,每行指定一种硬币类型,每行包含两个整数 P 和 W (1 <= P <= 50000,1 <= W <=10000)。P 是硬币的金额 (货币计量单位);W 是它的重量,以 g (克) 为计量单位。

输出
对于每组测试数据,打印一行输出。每行必须包含句子 “The minimum amount of money in the piggy-bank is X.” 其中,X 表示对于给定总重量的硬币,所能得到的最少金额。如果无法恰好得到给定的重量,则打印一行 “This is impossible.” 。

示例输入
3
10 110
2
1 1
30 50
10 110
2
1 1
50 30
1 6
2
10 3
20 4

示例输出
The minimum amount of money in the piggy-bank is 60.
The minimum amount of money in the piggy-bank is 100.
This is impossible.

一个关于完全背包的动态规划问题。(赛场上想用贪心做,结果菜鸡的我WA了好几发)
我看了看比赛别人的代码以及csdn上的代码用的都是同一种方法,状态以及状态转移方程应该都是一样的,但代码的实现方式不一样。
用dp[i]表示当容积为i的时候,最小重量。
则状态转移方程:d[i]=a[i]+d[i-b[j]]
这里的a[i]表示当前状态的重量,d[i-b[j]]表示上一个(不知道是具体哪一个,需要遍历)的状态。也就是说,上一个状态的最小重量,加本状态的重量,就是当前状态的最小重量。
代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
int dp[maxn];
int a[maxn],b[maxn];

int main()
 {

     int t,n,e,w;
     cin>>t;
     while(t--)
     {
         memset(dp,inf,sizeof(dp));
         dp[0]=0;
         cin>>e>>w;
         w-=e;
         cin>>n;
         for(int i=1;i<=n;i++)
            cin>>a[i]>>b[i];//a[i]是重量,b[i]是体积
         for(int i=1;i<=w;i++)
         {
             for(int j=1;j<=n;j++)
             {
                 if(b[j]<=i)//如果该硬币的体积比目标体积小
                 {
                     dp[i]=min(dp[i],dp[i-b[j]]+a[j]);
                 }
             }
         }
         if(dp[w]==inf)
            cout<<"This is impossible."<<endl;
         else
            cout<<"The minimum amount of money in the piggy-bank is "<<dp[w]<<"." <<endl;
     }

 }

ps:说实话,写出该题之后,再看csdn其他的代码感觉也没有那么不好理解了,思路应该都是大同小异,但我感觉我这个代码的实现方式比较好懂一些,我这个完全是按照刘汝佳紫书上DAG硬币问题来照着葫芦画瓢的233

做完这道题,感觉对dp有了初步的了解了,尤其是对与有固定终点的DAG模型。但毕竟才学了dp三四天,任重而道远。
共勉。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值