钱币组合问题

最近同事参加公司的黑客竞赛,有一道题目与钱币组合问题比较像,记得SICP里面有所描述,正好不是很忙,就试着实现该算法,用Scheme语言开发。


问题描述

假设我们已经有足够多的1分,2分,5分钱币,任意给定金额比如1元,问有多少种组合方式? 换言之,$$1x+2y+5z = 100$$ 求x,y,z的解有多少个


思路

组合方式的总和应为:

  1. 任意扣去一种钱币比如1分,1元采用2分,5分两种钱币的组合数,再加上:

  2. 总额为(1元-1分),采用1分,2分,5分三种钱币的组合数;

很明显这可以很容易用递归实现


稍作一点解释:

a. 上面两步的意思是:不带1分的组合数 + 带1分的组合数 = 全部的组合数; 这是显而易见的

b. 上述第2步,(1元-1分)的意思是:这样可以保证任意一种组合方式再加1分都等于1元,保证至少有1个1分的钱币

(letrec 
    [
        (A (lambda (n d) (if (= 0 (mod n d)) 1 0))) 
        (B (lambda (n d) 
                (cond
                    [(not (pair? d)) 0]
                    [(null? d) 0] 
                    [(= 0 n) 1] 
                    [(> 0 n) 0]
                    [(= 1 (length d)) (A n (car d))]
                    [else 
                        ( + (B n (cdr d)) (B (- n (car d)) d))
                    ]
                )
            )
        )
    ]

    [B 100 '(1 2 5)]
)