记忆是一种方式,另一种是使用不同的数据表示。
我使用表示为矩阵或向量向量的网格。
然后将顶行的值设置为 1(因为只有顶部边缘的路径。
之后,下一行的第一行是一个,第二个是上面第一列中条目的值,加上行中它之前的条目或值,
对行中的每个点进行递归,然后对每一行进行递归。
那么答案就是递归完成后最后一行的最后一个点。
对于 3x3 网格
1 1 1
1 2 3
1 3 6
6
在键非常接近的情况下(连续或几乎连续),向量表示将比散列更高效。
(define (make-lattice-point-square n)
(let ((lps (make-vector (+ n 1))))
(let loop ((i 0))
(if (> i n)
lps
(begin
(vector-set! lps i (make-vector (+ n 1)))
(loop (++ i)))))))
(define (lattice-ref lat x y)
;; where x is row, y is column thought it's not really important
(vector-ref (vector-ref lat y) x))
(define (lattice-set! lat x y value)
(vector-set! (vector-ref lat y) x value))
;; paths through a point are equal the the paths through the above point,
;; plus the paths through the left, those along the top and left edges
;; only have one possible path through them
(define (ways-exit-lattice n)
(let ((lps (make-lattice-point-square n)))
(letrec
((helper
(lambda (x y)
(if (or (= x 0) (= y 0))
(lattice-set! lps x y 1)
(lattice-set! lps x y
(+ (lattice-ref lps (- x 1) y)
(lattice-ref lps x (- y 1)))))))
(lattice-walker
(lambda (x y)
(cond ((and (= x n) (= y n))
(begin (helper x y) (lattice-ref lps x y)))
((= y n)
(begin
(helper x y)
(lattice-walker (++ x) 0)))
(else
(begin
(helper x y)
(lattice-walker x (++ y))))))))
(lattice-walker 0 0))))
注意所有对 latice-walker 的调用都是尾调用。
使用符合 RSR5 的方案