ハノイの塔 解説
TRANSCRIPT
問題ハノイの塔
• 問題: https://paiza.jp/learning/hanoi
• 3つの杭がある。
• 杭には円盤が置かれている。
• ある円盤の下には、大きい円盤しか置けない。
• 一番左の杭に積まれたn段の円盤を一番右に動かす。
• 最短の方法で移動した場合のt手目の状態を出力
• 1≤n≤16 0<t≤2^n-1
解法
• 一番右の杭について考えると、一番大きい円盤から順番に一番右の杭に置く必要がある。
• まず、一番大きい杭について考える。
• 一番大きい円盤を動かすためには、大きい円盤の上の円盤を真ん中の円盤に動かす必要がある。
解法• 関数定義: hanoi(n, 移動元、移動先、あまり)n段の円盤を移動元から移動先に移動する関数として定義する。
• hanoi(n-1、移動元、あまり、移動先)n-1段を移動元からあまりに移動する。
• 大きさnの円盤を異動元から移動先に移動する。
• hanoi(n-1, あまり、移動先、異動元) n-1段をあまりから移動先に移動する。
N, @T = gets.split.map(&:to_i) @t=0 @plates = [ N.downto(1).to_a,[],[] ] def show (0..2).each{|i| if @plates[i].size == 0 puts "-‐" else puts @plates[i].join(" ") end } end def move_one(n, from, to) plate = @plates[from].pop @plates[to].push(plate) @t += 1 if @t == @T show exit end end def hanoi(n, from, to, other) if n == 0 return end hanoi(n-‐1, from, other, to) move_one(n, from, to) hanoi(n-‐1, other, to, from) end hanoi(N, 0, 2, 1)
プレートを動かす回数• hanoi(n): n段の円盤を移動させるのに必要な回数
• hanoi(n) = hanoi(n-1) * 2 + 1
• hanoi(n)+1 = (hanoi(n-1)+1)*2
• hanoi(n)+1 = 2^n
• hanoi(n) = 2^n - 1n=16の場合、65535 => ok!
• 計算量: O(2^n)
コードdef hanoi(n, from, to, other) if n == 0 return end if @T >= @t + (2**n)-‐1 plates = @plates[from].pop(n) @plates[to].push(*plates) @t += (2**n -‐ 1) show if @t == @T return end …