可能的“船载”

时间:2010-08-07 21:06:18

标签: algorithm scheme lisp river-crossing-puzzle

你知道river-crossing problems。这是一种排序说明:

  

曾几何时,三名食人族正在通过丛林引导三名传教士。他们正在前往最近的任务站的路上。过了一段时间,他们到达了一条宽阔的河流,满是致命的蛇和鱼。没有船就没有办法过河。幸运的是,经过短暂的搜索,他们发现了一艘带有两个桨的划艇。不幸的是,这艘船太小而无法携带所有这些船。它一次几乎不能携带两个人。更糟糕的是,由于河流的宽度,除了将船拖回去之外,没有办法把船拉回来。   由于传教士不能相信食人族,他们不得不制定一项计划,让所有六人安全地过河。问题是这些食人族会在一些地方有更多的食人族而不是传教士时会杀死和吃传教士。因此,我们的传教士程序员必须制定一项计划,保证在河的两边都没有少数传教士。然而,可以信任食人族以其他方式合作。具体而言,他们不会放弃任何潜在的食物,就像传教士不会放弃任何潜在的皈依者一样。

我的问题是这个问题的一部分。我正在尝试设计一个返回可能船载量列表的函数(例如,如果boat_capacity为3然后 [(3mis,0can),(2mis,1can),(1mis,1can),...] )。我有 num (传教士或食人族的数量)和船容量作为我的功能的输入。

您如何设计您的功能和算法?

4 个答案:

答案 0 :(得分:1)

以递归的方式思考这个问题,也就是说你想根据可能的子问题来考虑它。所以,如果你有三个乘客的船,那显然就像一艘有一个乘客的船,加上两个乘客的任何组合。

一艘有两名乘客的船只有一名乘员加上“一艘满载一名乘客的船”。

所以你的算法基本上看起来像

to find all combinations of n occupants,
    pick an occupant
    if n = 1 return
    if n > 1 find all combinations of (n-1) occupants.

请注意,这不是完全解决方案,因为这看起来很像家庭作业问题。

答案 1 :(得分:1)

我在Scheme环境中解决了这个问题。可能它不是很快,但它确实有效。

;;; boat-loads : mc_num  boat_capacity --> list of boat_loads 
;;; returns a list of possible (cannibals cannot be more than missionaries)
;;; boat-loads

(define (boat-loads mc bc storage)
 (local 
  ((define isBoatBig (> bc mc))
   (define (both  mc bc storage)
     (cond 
         [(< mc 1) storage]
         [else 
          (both (- mc 1) bc (append storage (list (list mc (- bc mc)))))]))
   (define (single mc bc storage)
    (cond 
      [(= mc 0) storage]
      [else 
       (single (- mc 1) bc (append storage (list (list mc 0) (list 0 mc))))]))
  (define (filt l)
    (local
      ((define (filter-equal l acc)
         (local 
           ((define (filter-equal-inner f  l)
              (cond 
                [(empty? l) (list f)]
                [(equal? f (first l))  (filter-equal-inner (first l) (rest l))]
                [else (append (list (first l))
                              (filter-equal-inner f (rest l)))]))
            (define done (filter-equal-inner (first l) (rest l))))
           (cond 
             [(= 0 acc) done]
             [else (filter-equal done (- acc 1))]))))
       (filter-equal l (length l)))))
  (cond
   [(= bc 0) storage]
   [else 
    (filt (boat-loads mc
                      (- bc 1)
                      (append storage
                              (if isBoatBig 
                                  (filter (lambda (x)
                                            (if (>= (first x) (second x))
                                                true false))
                                          (append (both mc bc empty)
                                                  (single mc bc empty)))
                                  (filter (lambda (x)
                                            (if (>= (first x) (second x))
                                                true false))
                                          (append (both bc bc empty)
                                                  (single bc bc empty)))))))])))

答案 2 :(得分:1)

或者您可以将其视为生成长度为1,2的所有字符串,以及由两个符号组成的3。比如,例如,MC。或者,嗯,零和一个! 0为传教士,1为食人族。

010011000111。生成它们的“方法”现在就跳出来了,对吧?

答案 3 :(得分:0)

您的问题类似于Escape from Zurg