找零问题多解

Description

小李是超市的收银员,每当顾客来结账时,他们给的钱往往都多于他们所购物品的实际价格,这时,小李就需要找零给他们。小李是一个很爱思考的人,他想知道在目前的纸币面额情况下(1角、5角、1元、5元、10元、20元、50元、100元),如果每种面额的纸币的数量都是无限的,他要给一个顾客找零N(0<N<100)元有多少种方式(如0.5元有两种方式:5个1角和1个5角)。小李很苦恼这个问题,聪明的你能帮助他吗?

Input

输入包括多组测试用例,通过EOF结束。
每组测试用例包括一行,为一个数N(1<N<100),N为最多包含一位小数的实数。

Output

对于每组测试用例,输出一行,为一个整数,表示找零的方法总数。

Sample Input

0.5
1

Sample Output

2
4

对普通的三、四种货币的找零问题比较简单,只要想法不超时,n重for循环解决

但对于多种货币,那就无法用多重循环。下面有两种方法,我理解的很困难(cry:

方法一:

先看几种基本情况

 可以发现分解总是找离它最近的基本数依次递减逐层分解,所以每层都是一个嵌套的情况

#include<stdio.h>
int count=0;
const int A[]={1,5,10,50,100,500,1000};
void change(int x,int top){
    printf("%d %d %d\n",x,top,count);
    if(x==0){
        count++;//递归边界,就是A【top】的组成和与x相同了
        return ;
    }
    if(top<0) return ;//超过了我们基的范围
    change(x,top-1);//看下一个基组成x的情况
    int i; 
    for(i=A[top];i<=x;i+=A[top]){
        change(x-i,top-1);//看这个A【top】逐递增的被它的下一个基表示的情况
    }
}
int main(){
    double x;
    scanf("%lf",&x);
    int m=10*x;
    change(m,6);
    printf("%d\n",count);
}

方法二:

有点类似方法一的逆运算。

#include<stdio.h>
const int A[]={1,5,10,50,100,500,1000};
int main(){
    double x;
    int m;
    scanf("%lf",&x);
    m=x*10;
    int a[100]={};
    a[0]=1;
    int i,j;
    for(i=0;i<8;i++){
        for(j=1;j<=m;j++){
            if(j>=A[i]){//如果比基元大,那么可以说明该基构成该数至少有一种情况
                a[j]+=a[j-A[i]];//理解请结合下图
                //printf("%d %d\n",j,a[j]);
            }
        }    
    }
    printf("%d\n",a[m]);
}

以1为例输出

发现1能构成一种情况,构成5有两种情况,所以构成10由于有次基5,和次次基10,所以构成情况有4种。

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值