目标:总计:10 denoms:(10 5 1) 返回((10)(5 5)(5 1 1 1 1 1)(1 1 1 1 1 1 1 1 1 1))
我的代码:
(define (changes-list total denoms)
(cond
((null? denoms) nil )
((= total 0 ))
((> (car denoms) total) (changes-list total (cdr denoms)))
(else
(if (= total (car denoms)) (cons (list (car denoms)) (changes-list total (cdr denoms)))
(append (cons-all (car denoms) (changes-list (- total (car denoms)) denoms))))
) ) )
~~~~~~ 我的代码现在输出的是:((10)(5 5)(5 1 1 1 1 1)) 我认为问题可能在于cond,当我调用change-list on(cdr denoms)并且更改为空时退出并退出但我不知道如何解决这个问题。非常感谢所有帮助!!
答案 0 :(得分:0)
假设有以下两个条件(否则你应该检查参数):
total
始终是非负面的,denoms
按递减顺序排序,最后一个元素始终为1
,这是一个可能的解决方案:
(define (cons-all x lst)
(map (lambda (l) (cons x l)) lst))
(define (repeat n x)
(if (= n 0)
'()
(cons x (repeat (- n 1) x))))
(define (changes-list total denoms)
(cond ((= total 0) '(()))
((null? (cdr denoms)) (list (repeat total (car denoms))))
((< total (car denoms)) (changes-list total (cdr denoms)))
(else (append (cons-all (car denoms) (changes-list (- total (car denoms)) denoms))
(changes-list total (cdr denoms))))))
(changes-list '6 (2 1)) ; => ((2 2 2) (2 2 1 1) (2 1 1 1 1) (1 1 1 1 1 1))
答案 1 :(得分:0)
当尝试不同的路径并不是每个人都会产生有效的解决方案时,我喜欢使用path
列表来跟踪路径,而累加器acc
只能保留成功的结果:< / p>
(define (changes-list total denoms)
(let iter ((total total) (denoms denoms) (path '()) (acc '()))
(cond
((= total 0) (cons (reverse path) acc)) ; the current path lead to a solution => keep path in accumulator
((or (< total 0) (null? denoms)) acc) ; discard path
(else
(let ((denom (car denoms))) ; first denomination
(iter (- total denom) ; (1) use first denomination
denoms
(cons denom path)
(iter total ; (2) drop first denomination
(cdr denoms)
path
acc)))))))
测试:
> (changes-list 10 '(10 5 1))
'((10) (5 5) (5 1 1 1 1 1) (1 1 1 1 1 1 1 1 1 1))
> (changes-list 6 '(2 1))
'((2 2 2) (2 2 1 1) (2 1 1 1 1) (1 1 1 1 1 1))