Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
Chargement dans…3
×
1 sur 13

ハノイの塔 解説

1

Partager

Télécharger pour lire hors ligne

ハノイの塔 解説

Livres associés

Gratuit avec un essai de 30 jours de Scribd

Tout voir

ハノイの塔 解説

  1. 1. ハノイの塔 解説 ギノ株式会社 吉岡 恒夫
  2. 2. 問題 ハノイの塔 • 問題: https://paiza.jp/learning/hanoi • 3つの杭がある。 • 杭には円盤が置かれている。 • ある円盤の下には、大きい円盤しか置けない。 • 一番左の杭に積まれたn段の円盤を一番右に動かす。 • 最短の方法で移動した場合のt手目の状態を出力 • 1≤n≤16 0<t≤2^n-1
  3. 3. 解法 • 一番右の杭について考えると、一番大きい円盤 から順番に一番右の杭に置く必要がある。 • まず、一番大きい杭について考える。 • 一番大きい円盤を動かすためには、大きい円盤 の上の円盤を真ん中の円盤に動かす必要がある。
  4. 4. 解法
  5. 5. 解法 • 関数定義: hanoi(n, 移動元、移動先、あまり) n段の円盤を移動元から移動先に移動する関数として定 義する。 • hanoi(n-1、移動元、あまり、移動先) n-1段を移動元からあまりに移動する。 • 大きさnの円盤を異動元から移動先に移動する。 • hanoi(n-1, あまり、移動先、異動元) n-1段をあまりから移動先に移動する。
  6. 6. コード
  7. 7. 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)
  8. 8. プレートを動かす回数 • 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 - 1 n=16の場合、65535 => ok! • 計算量: O(2^n)
  9. 9. ところで • 本物(?)のハノイの塔は64段! • もし n = 64なら? • 移動回数 2^64-1= 18446744073709551615 (1秒に一回移動させるとして1000億年)
  10. 10. 解法2 • nがT以下の場合、シミュレーションしなくても、 動かしたことにしてしまえばいい!
  11. 11. コード 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 …
  12. 12. 計算量 • 解法1(総当たり) O(2^n) • 解法2(最適化後) O(n) # 各nについてhanoiは一回のみ呼ばれる

×