题目源于《SICP》,这里做一下调整,如下:
给了面值为50元、20元、10元、5元、1元的五种零钱若干,思考把面值100元人民币换成零钱一共有多少种方式?
SICP给出的递归算法思想如下:
将总数为a的现金换成n种不同面值的不同方式的数目等于:
将现金a换成除了第一种面值之外的所有其他面值的不同方式数目,加上
将现金a-d换成所有种类的面值的不同方式数目,其中d是第一种面值的钱币
下面有解释到,递归的思想是要将问题归约到对更少现金数或更多种类面值钱币的同一个问题。有如下的约定:
如果a==0,应该算作是有1种换零钱的方式
如果a<0,应该算作是有0中换零钱的方式
如果n=0,应该算作是有0种换零钱的方式
大家先不要纠结于为何要有这种约定,只需要记住这个约定就好了,先看看Lisp代码的实现:
(define (count-change amount)
(cc amount 5)
)
(define (cc amount kinds-of-coins)
(cond ((= amount 0) 1)
((or (< amount 0) (= kinds-of-coins 0)) 0)
(else ( + (cc amount (- kinds-of-coins 1))
(cc (- amount (first-denomination kinds-of-coins) kinds-of-coins))
)
)
)
(define (first-denomination kinds-of-coins)
(cond ((= kinds-of-coins 1) 1)
((= kinds-of-coins 2) 5)
((= kinds-of-coins 3) 10)
((= kinds-of-coins 4) 20)
((= kinds-of-coins 5) 50)
)
)
如果对Lisp有点儿晕,可以看看等价的Java实现:
//换零钱
public stat