Comment detail

必ず解ける迷路 (Nested Flatten)

棒倒し法で上から作ると O(n) で済むのでは……って 、もう #5296 で指摘されてますね。

出題者さんの用意した方法も想像はついているのですが、それなりに頑張らないと実装できそうにないのでパスしました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
(defun make-maze-1 (upper middle lower &optional arg) ; arg: 最初の行なら真
  (do ((i 1 (+ i 2)))
      ((>= i (length upper)))
    (loop
      (let ((r (random (if arg 4 3))))
        (when (char= #\IDEOGRAPHIC_SPACE
                     (case r
                       (0 (elt middle (1- i)))
                       (1 (elt middle (1+ i)))
                       (2 (elt lower i))
                       (3 (elt upper i))))
          (return (case r
                    (0 (setf (elt middle (1- i)) #\BLACK_SQUARE))
                    (1 (setf (elt middle (1+ i)) #\BLACK_SQUARE))
                    (2 (setf (elt lower i) #\BLACK_SQUARE))
                    (3 (setf (elt upper i) #\BLACK_SQUARE)))))))))

(defun make-maze (m n)
  (let* ((w (+ n n -1))                 ; 迷路の幅
         (whites (make-string w :initial-element #\IDEOGRAPHIC_SPACE))
         (blacks (make-string w :initial-element #\BLACK_SQUARE))
         (alt (let ((s (copy-seq whites)))
                (loop for i from 1 below w by 2 do
                  (setf (elt s i) #\BLACK_SQUARE))
                s))
         (upper (copy-seq whites))
         (middle (copy-seq alt))
         (lower (copy-seq whites))
         (*random-state* (make-random-state t)))
    (format t "■~A■~%" blacks) ; 上の壁
    (make-maze-1 upper middle lower t)
    (format t "■~A■~%■~A■~%" upper middle)
    (dotimes (i (- m 2))
      (replace upper lower)
      (replace middle alt)
      (replace lower whites)
      (make-maze-1 upper middle lower)
      (format t "■~A■~%■~A■~%" upper middle))
    (format t "■~A■~%" lower)
    (format t "■~A■~%" blacks) ; 下の壁
    ))

所要時間は Celeron 2.66GHz, CLISP で 2.84 秒でした。

棒倒し法、たしかにO(n)ですね。

ご想像のとおり、私の意図したアルゴリズムは実装がちょっと面倒です。

Index

Feed

Other

Link

Pathtraq

loading...