Dollars uva 147

Time limit: 3.000 seconds
限时:3.000秒

 

Problem
问题

New Zealand currency consists of  100, 50,  20, 10, and  5notesand 2, $1, 50c, 20c, 10c and 5c coins. Write a program that will determine, for any given amount, in how many ways that amount may be made up. Changing the order of listing does not increase the count. Thus 20c may be made up in 4 ways: 1 × 20c, 2 × 10c, 10c+2 × 5c, and 4 × 5c.
新西兰的流通货币中,纸币分为五种:100元、50元、20元、10元和5元;硬币分为六种:2元、1元、50分(即五毛)、20分、10分和5分。写一个程序计算出对于给定的任意金额,可以有多少种不同的钱币组合方式。仅仅改变顺序的不能算。比如20分可以有以下4种组合方式:1 × 20分, 2 × 10分, 10分+2 × 5分, 和4 × 5分。

 

Input
输入

Input will consist of a series of real numbers no greater than $300.00 each on a separate line. Each amount will be valid, that is will be a multiple of 5c. The file will be terminated by a line containing zero (0.00).
输入由一组实数构成,每个实数都不会超过300.00元,并且都独占一行。金额都是有效的,即都是5分的整数倍。输入由一行零元(0.00)表示结束。

 

Output
输出

Output will consist of a line for each of the amounts in the input, each line consisting of the amount of money (with two decimal places and right justified in a field of width 6), followed by the number of ways in which that amount may be made up, right justified in a field of width 17.
每行输入对应一行输出,包括总金额(保留两位小数并右对齐至第6列),后面是可以组成该金额的方法数,右对齐宽度为17。

 

Sample Input
输入示例

0.20
2.00
0.00

 

Sample Output
输出示例

  0.20                4
  2.00              293

 

Analysis
分析

此题较难,是一个子集合问题。可以用递归式直接计算任意给定金额的组合方案,但是所给的数据可能非常大,用递归的话肯定会TLE,因此必须通过递推的方式生成所有可能金额的答案,运行时直接查表即可。

建表过程如下:首先任何金额都可仅由5分组成这1种方案,如果金额刚好等于某一种钱币,就还有这一种方案,因此10分有2种方案。15分的第一种方案可仅由5分组成,要计算由10分或5分组成(不包括前面算过的全部5分的情况)的情况,可先减掉10分(因为这种情况至少包括一个10分),剩下的5分就只有1种情况,因此共有2种方案。20分的第一种方案可由5分组成;第二种情况先减掉10分还剩10分,而10分由10分或5分组成的情况有2种,因此都要计入;最后一种方案就是直接使用20分,因此一共4种方案。其余的以此类推。

10分中有5分参与的可能怎样算  先减去5分表示已经有一个5分剩下的钱有几种可能就是就是几种可能(但是这些钱只能有5分及其以下的硬币组成)这样就避免

重复,因为10分的也要朝下算,5分的朝上算的话就重复了。举个例子30分有5分一定参与及其以下组成的有1中可能,10分一定参与及其以下的组成由3种可能,20分参与及其以下的有2中可能总共有6中可能

注意到所有钱数都是5的整数倍,因此可以将货币面值和查询的金额统一除以5再计算。要注意按指定的格式输出结果,并在输入0时退出程序。


 

Solution
解答

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iomanip>
#include <iostream>
using  namespace  std;
int  main( void ) {
     //钱币数,全部除以5
     int  Coins[] = {1, 2, 4, 10, 20, 40, 100, 200, 400, 1000, 2000};
     long  long  Tbl[6001] = {1}; //各金额组合方案数总表
     //以下开始建表,按钱币种类进行循环
     for  ( int  i = 0; i < 11; i++){
         //仅使用i之前的钱币进行组合,但不包括不使用i的情况
         for  ( int  j = Coins[i]; j < 6001; j++) {
             //先减掉第i种钱币,然后加上剩下的金额的组合方案数
             Tbl[j] += Tbl[j - Coins[i]];
         }
     } //以下为设定格式,查表输出结果。
     cout << fixed << showpoint << setprecision(2);
     for  ( float  fIn; cin >> fIn && fIn != 0; cout << endl) {
         cout << setw(6) << fIn << setw(17) << Tbl[( int )(fIn * 20 + 0.5f)];
     }
     return  0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值