鱼C论坛

 找回密码
 立即注册
查看: 4597|回复: 9

题目31:考察英国货币面值的组合问题

[复制链接]
发表于 2015-4-23 23:33:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 欧拉计划 于 2015-4-23 23:35 编辑
Coin sums

In England the currency is made up of pound, £, and pence, p, and there are eight coins in general circulation:

1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) and £2 (200p).
It is possible to make £2 in the following way:

1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p
How many different ways can £2 be made using any number of coins?

题目:

在英国,货币是由英镑 £,便士 p 构成的。一共有八种钱币在流通:

1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) 和 £2 (200p).
要构造 £2 可以用如下方法:

1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p

允许使用任意数目的钱币,一共有多少种构造 £2 的方法?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-4-25 22:25:15 | 显示全部楼层
本帖最后由 lightninng 于 2015-5-1 19:59 编辑

python版块的我来凑个热闹
1、解题思路:把问题由大划小,先想一个数用一种货币有多少种组合方法;在一种的基础上想两种货币怎么解决,可以想到,一种货币的数目固定了,另外一种的数目就固定了;在两种的基础上想三种,同理,两种的数目确定了便可以确定第三种的数目
基于此,递归函数解决的问题为,用n种不同的货币组成总钱数为m的方法的数目
例如,总数为200钱币,面值为100的钱币可以有三种选择方法,0,1,2,则在100的钱币为0,1,2的时候用剩下的面值的钱币分别组合成200,100,0即可
2、代码如下:
  1. COUNT = 0  # 变量用于存储构造方法的数目


  2. def coin_sums(pre_sum, coin_values, sum_value):
  3.     global COUNT
  4.     if len(coin_values) == 1:
  5.         if sum_value % coin_values[0] == 0:
  6.             COUNT += 1
  7.             # print(pre_sum +
  8.             #      "{0}*{1}p".format(sum_value//coin_values[0], str(coin_values[0])))
  9.     else:
  10.         for i in range(sum_value//coin_values[0] + 1):
  11.             coin_sums(pre_sum + "{0}*{1}p + ".format(i, str(coin_values[0])),
  12.                       coin_values[1:], sum_value-i*coin_values[0])

  13. target = 200
  14. coin_sums("{}p = ".format(str(target)),  [100, 50, 20, 10, 5, 2, 1], target)
  15. print(COUNT)
复制代码
运行结果
  1. >>> ================================ RESTART ================================
  2. >>>
  3. 73681
  4. >>>
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-9-22 15:05:13 | 显示全部楼层
还缺1种,就是由2磅本身构成的。所以应该是
73682种

73682
[Finished in 5.5s]

  1. count = 1
  2. for a in range(3):
  3.         if a * 100 <= 200:
  4.                 for b in range(5):
  5.                         if a * 100 + b *50 <= 200:
  6.                                 for c in range(11):
  7.                                         if a * 100 + b * 50 + c * 20 <= 200:
  8.                                                 for d in range(21):
  9.                                                         if a * 100 + b * 50 + c * 20 + d * 10 <= 200:
  10.                                                                 for e in range(41):
  11.                                                                         if a * 100 + b * 50 + c * 20 + d * 10 + e * 5 <= 200:
  12.                                                                                 for f in range(101):
  13.                                                                                         if a * 100 + b * 50 + c * 20 + d * 10 + e * 5 + f * 2 <= 200:
  14.                                                                                                 for g in range(201):
  15.                                                                                                         if a * 100 + b * 50 + c * 20 + d * 10 + e * 5 + f * 2 + g == 200:
  16.                                                                                                                 count += 1
  17. print (count)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-13 13:32:39 | 显示全部楼层
  1. # encoding:utf-8
  2. # 英镑组合问题
  3. from time import time
  4. def euler031():
  5.     count = 0
  6.     for i in (0, 1):  # 1磅
  7.         for j in (0, 1, 2, 3):  # 50便士
  8.             if i * 100 + j * 50 > 200:
  9.                 break
  10.             for l in range(0, 10):  # 20便士
  11.                 if i * 100 + j * 50 + l * 20 > 200:
  12.                     break
  13.                 for k in range(0, 20):  # 10便士
  14.                     if i * 100 + j * 50 + l * 20 + k * 10 > 200:
  15.                         break
  16.                     for m in range(0, 40):  # 5便士
  17.                         if i * 100 + j * 50 + l * 20 + k * 10 + m * 5 > 200:
  18.                             break
  19.                         for n in range(0, 100):  # 2便士
  20.                             if i * 100 + j * 50 + l * 20 + k * 10 + m * 5 + n * 2 > 200:
  21.                                 break
  22.                             for o in range(0, 200):  # 1便士
  23.                                 tmp = i * 100 + j * 50 + l * 20 + k * 10 + m * 5 + n * 2 + o
  24.                                 if tmp == 200:
  25.                                     count += 1
  26.                                 # print(i, j, k, m, n, o)
  27.                                     break
  28.                                 if tmp > 200:
  29.                                     break
  30.     # 加上7种一种面值组成的  如果2磅也算的话  加8种
  31.     print(count + 7)      
  32. if __name__ == '__main__':
  33.     start = time()
  34.     euler031()
  35.     print('cost %.6f sec' % (time() - start))
复制代码


73681
cost 1.730173 sec
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-23 21:24:01 | 显示全部楼层
本帖最后由 渡风 于 2017-1-23 21:38 编辑

此代码使用matlab编程
Problem31所用时间为2.0718秒
Problem31的答案为73682
感谢楼上的兄弟提供的思路
  1. %% Problem31
  2. % 题目31:考察英国货币面值的组合问题
  3. %细节 Break的使用
  4. function Output=Problem31(Input)
  5. tic
  6. if nargin==0
  7. Input=200;
  8. end
  9. tic
  10. Type=0;
  11. for a1=0:Input
  12.     for a2=0:100
  13.         if a1+2*a2>Input
  14.             break
  15.         end
  16.         for a3=0:40
  17.             if a1+2*a2+5*a3>Input
  18.                 break
  19.             end
  20.             for a4=0:20
  21.                 if a1+2*a2+5*a3+10*a4>Input
  22.                     break
  23.                 end
  24.                 for a5=0:10
  25.                     if a1+2*a2+5*a3+10*a4+20*a5>Input
  26.                         break
  27.                     end
  28.                     for a6=0:4
  29.                         if a1+2*a2+5*a3+10*a4+20*a5+50*a6>Input
  30.                             break
  31.                         end
  32.                         for a7=0:1
  33.                             if a1+2*a2+5*a3+10*a4+20*a5+50*a6+100*a7==Input
  34.                                 Type=Type+1;
  35.                             end
  36.                         end
  37.                     end
  38.                 end
  39.             end
  40.         end
  41.     end
  42. end
  43. Type=2+Type;%一张200磅,两张100磅
  44. Output=Type;
  45. toc
  46. toc
  47. disp('此代码使用matlab编程')
  48. disp(['Problem31所用时间为',num2str(toc),'秒'])
  49. disp(['Problem31的答案为',num2str(Output)])
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-7-29 14:20:48 | 显示全部楼层
  1. public class CoinSums{
  2.         public static void main(String[] args){
  3.                 int sum = 0,count = 1;
  4.                 for(int hundred = 0;hundred <= 2;hundred++){
  5.                         sum = 0;
  6.                         sum = 100*hundred;
  7.                         if(sum > 200){
  8.                                 continue;
  9.                         }
  10.                         for(int fifty = 0;fifty <= 4;fifty++){
  11.                                 sum = 100*hundred+50*fifty;
  12.                                 if(sum > 200){
  13.                                         continue;
  14.                                 }
  15.                                 for(int twenty = 0;twenty <= 10;twenty++){
  16.                                         sum = 100*hundred+50*fifty+20*twenty;
  17.                                         if(sum > 200){
  18.                                                 continue;
  19.                                         }
  20.                                         for(int ten = 0;ten <= 20;ten++){
  21.                                                 sum = 100*hundred+50*fifty+20*twenty+10*ten;
  22.                                                 if(sum > 200){
  23.                                                         continue;
  24.                                                 }
  25.                                                 for(int five = 0;five <= 40;five++){
  26.                                                         sum = 100*hundred+50*fifty+20*twenty+10*ten+5*five;
  27.                                                         if(sum > 200){
  28.                                                                 continue;
  29.                                                         }
  30.                                                         for(int two = 0;two <= 100;two++){
  31.                                                                 sum = 100*hundred+50*fifty+20*twenty+10*ten+5*five+2*two;
  32.                                                                 if(sum > 200){
  33.                                                                         continue;
  34.                                                                 }
  35.                                                                 for(int one = 0;one <= 200;one++){
  36.                                                                         sum = 100*hundred+50*fifty+20*twenty+10*ten+5*five+2*two+one;
  37.                                                                         if(sum == 200){
  38.                                                                                 count ++;
  39.                                                                                 System.out.print("第"+count+"种情况");
  40.                                                                                 System.out.println(hundred+"\t"+fifty+"\t"+twenty+"\t"+ten+"\t"+five+"\t"+two+"\t"+one);
  41.                                                                         }
  42.                                                                 }
  43.                                                         }
  44.                                                 }
  45.                                         }
  46.                                 }
  47.                         }
  48.                 }
  49.         }
  50. }
复制代码

73682
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-6-13 10:36:15 | 显示全部楼层
73682
  1. count = 0


  2. def get_target(values, target):
  3.     global count
  4.     if len(values) > 1:
  5.         for i in range(target//values[0] + 1):
  6.             get_target(values[1:], target - i*values[0])
  7.     else:
  8.         count += 1
  9.     return count

  10. values = [200, 100, 50, 20, 10, 5, 2, 1]
  11. target = 200
  12. get_target(values, target)
  13. print(count)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-7 17:06:38 | 显示全部楼层
73682
动态规划之无限背包问题,状态转移方程为

                               
登录/注册后可看大图

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstring>
  4. using namespace std;

  5. const int coin[] = {1,2,5,10,20,50,100,200};
  6. int comb[10][205];

  7. int dp(int i,int sum){
  8.   //cout << i << " " << sum << endl;
  9.   //if (sum == 0) {cnt++; return 0;}
  10.   if (i == 1) return comb[i][sum] = 1;
  11.   if (comb[i][sum] >= 0)  return comb[i][sum];
  12.   int k = sum / coin[i-1];

  13.   int res = 0;
  14.   for (int j = 0;j <= k;j++)
  15.     res += dp(i-1,sum - j*coin[i-1]);
  16.   return comb[i][sum] = res;
  17. }

  18. int main(){
  19.   memset(comb,-1,sizeof(comb));
  20.   cout << dp(8,200) << endl;
  21.   return 0;
  22. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2021-3-14 13:51:42 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <time.h>

  3. main()
  4. {
  5.         int sum, count = 0;
  6.         int begin = time(0), end;

  7.         for (int a = 0; a <= 2; a++)
  8.         {
  9.                 if (a == 2)
  10.                 {
  11.                         count++;
  12.                         break;
  13.                 }
  14.                 for (int b = 0; b <= 4; b++)
  15.                 {
  16.                         for (int c = 0; c <= 10; c++)
  17.                         {       
  18.                                 for (int d = 0; d <= 20; d++)
  19.                                 {
  20.                                         for (int e = 0; e <= 40; e++)
  21.                                         {       
  22.                                                 for (int f = 0; f <= 100; f++)
  23.                                                 {
  24.                                                         for (int g = 0; g <= 200; g++)
  25.                                                         {
  26.                                                                 sum = a * 100 + b * 50 + c * 20 + d * 10 + e * 5 + f * 2 + g;
  27.                                                                 if (200 == sum)
  28.                                                                 {
  29.                                                                         count++;
  30.                                                                 }
  31.                                                         }
  32.                                                 }
  33.                                         }
  34.                                 }
  35.                         }
  36.                 }
  37.         }
  38.         end = time(0);
  39.         printf("%d\n", count + 1);
  40.         printf("time = %ds\n", end - begin);
  41. }
复制代码


73682
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-3 10:41:30 | 显示全部楼层
本帖最后由 guosl 于 2022-1-3 10:43 编辑
  1. /*
  2. 动态规划
  3. 答案:73682
  4. */
  5. #include <iostream>
  6. using namespace std;

  7. int a[8] = { 1, 2, 5, 10, 20, 50, 100,200 };//各种币值
  8. long long f[201] = { 1 };//f[k]表示k值可以有多少种构造方式

  9. int main(void)
  10. {
  11.   //动态转移方程
  12.   for (int i = 0; i < 8; ++i)//对钞票的种类进行枚举
  13.   {
  14.     for (int j = 200; j >= a[i]; --j)//对要构造的值j进行枚举
  15.     {
  16.       for (int k = 1; k * a[i] <= j; ++k)//对构造的钞票张数进行枚举
  17.         f[j] += f[j - k * a[i]];//在原来基础上添加k张值为a[i]便士的钞票
  18.     }
  19.   }
  20.   cout << f[200] << endl;
  21.   return 0;
  22. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-19 17:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表