2

私はロバート・セッジウィックのアルゴリズムを読んでいます

以下は、数値の2進表現における後続ゼロの数に関する213ページからの抜粋です。

ハノイの塔の問題の場合、nビット数との対応の意味はタスクの単純なアルゴリズムです。完了するまで2つの手順を実行することで、パイルを1ペグ右に移動できます。

  1. nが奇数の場合は小さなディスクを右に移動します(nが偶数の場合は左に移動します)
  2. 小さなディスクを含まない唯一の合法的な動きをしてください。

つまり、小さなdsikを移動した後、他の2つのペグには2つのディスクが含まれ、一方が他方よりも小さくなります。小さいディスクを含まない唯一の合法的な移動は、小さいディスクを大きいディスクに移動することです。1つおきの数字が奇数であり、ルール上の1つおきのマークが最短であるのと同じ理由で、1つおきの移動には小さいディスクが含まれます。

上記のテキストは、情報からさまざまな参考資料を読んだ後でも、頭に浮かびません。

ディスクN=3などの簡単な例を教えてください。Disk3が最大でDisk1が最小であり、PegAからPegBに移動する必要があります。

Disk1
Disk2
Disk3
-------       ------------         ------------
Peg A            Peg B                 Peg C
4

3 に答える 3

4

ここで最初に注意することは、このアルゴリズムでは、最初のペグが最後のペグの右側であると見なされ、最後のペグが最初のペグの左側であると見なされることです。

リストされている2つの手順を繰り返し適用すると、nディスクのタワーが1つのペグで右に移動します。

の場合n = 3nは奇数なので、2つの動きは次のとおりです。

  1. Disk11つのペグを右に移動します。
  2. を含まない唯一の合法的な動きをしDisk1ます。

これらの動きを繰り返すことによって次の解決策を与える:

  1. Disk1: PegA -> PegBDisk11つのペグを右に移動します)
  2. Disk2: PegA -> PegC(関与しない合法的な動きのみDisk1
  3. Disk1: PegB -> PegCDisk11つのペグを右に移動します)
  4. Disk3: PegA -> PegB(関与しない合法的な動きのみDisk1
  5. Disk1: PegC -> PegADisk11つのペグを右に移動します)
  6. Disk2: PegC -> PegB(関与しない合法的な動きのみDisk1
  7. Disk1: PegA -> PegBDisk11つのペグを右に移動します)

彼が「nビット数との対応」と書いているとき、Sedgewickはk、ソリューションのステップで移動するディスクが、の2進表現の最下位1ビットに対応するディスクであるという事実に言及していますk。すなわちn = 3

step | bits | disk
------------------
  1  |  001 |  1
  2  |  010 |  2
  3  |  011 |  1
  4  |  100 |  3
  5  |  101 |  1
  6  |  110 |  2
  7  |  111 |  1
于 2012-09-10T09:29:38.273 に答える
0

この特定の問題の解決策は次のとおりです。に移動Disk1Peg Bに移動Disk2Peg Cに移動Disk1Peg Cに移動Disk3Peg Bに移動Disk1Peg Aに移動Disk2、にPeg B移動。終わり。Disk1Peg B

于 2012-09-10T08:59:18.827 に答える
0

これが誰かを助ける場合に備えて、私はここにPythonで完全なソリューションを書きました:https ://github.com/goblinhack/towers-of-hanoi

#!/usr/bin/env python
#
# The way to solve this is quite simple but does differ slightly for N = odd or even numbers of rings.
# 
# At each move you do either a) or b):
# 
# a) move the "1" value to the peg to the right, wrapping around to the first peg if needed
# 
# b) make the only other legal move
# 
# And then repeat either a) or b) for (2 ^ numrings) - 1.
# 
# So for N=3, you would do the above steps 7 times.
# 
# The catch that I alluded to earlier is that for N == odd (3,5,...), you will need to repeat this
# entire algorithm one more time as the above will only move the rings one peg to the right. 
#
import sys

#
# Print the tower so we can check our progress
#
def print_tower(pegs, nrings):
    npegs = len(pegs)
    for y in range(0, nrings):
        h = nrings - y
        for x in range(0, npegs):
            if len(pegs[x]) >= h:
                sys.stdout.write(str(pegs[x][len(pegs[x]) - h]) + " ")
            else:
                sys.stdout.write("| ")
        print("")
    print("-----")

def solve_tower(nrings, npegs):
    pegs = []
    for peg in range(0, npegs):
        pegs.append([])

    #
    # push the nrings on
    #
    for i in range(0, nrings):
        pegs[0].append(i + 1)

    #
    # For N == odd numbers we will need to repeat this twice
    #
    for tries in range(0, 1 + nrings % 2):
        print_tower(pegs, nrings)
        move_peg_one_right = True

        #
        # Repeat the steps a) or b) for 2^N-1 times
        #
        for moves in range(0, (1 << nrings) - 1):
            #
            # step a)
            #
            if move_peg_one_right:
                for peg in range(0, npegs):
                    if len(pegs[peg]):
                        if pegs[peg][0] == 1:
                            next_peg = (peg + 1) % npegs
                            pegs[next_peg].insert(0, pegs[peg].pop(0))
                            print("Moving value 1 from peg {} to peg {}\n".format(peg + 1, next_peg + 1))
                            break
            else:
                #
                # step b)
                #
                moved_a_ring = False
                for peg in range(0, npegs):
                    #
                    # Look for a ring on a peg to move
                    #
                    if len(pegs[peg]):
                        value = pegs[peg][0]
                        #
                        # Don't move the ring value "1" as we move that in a)
                        #
                        if value != 1:
                            for next_peg in range(0, npegs):
                                #
                                # The next peg is the one to the right of this peg. If we reach the last peg then we
                                # need to move to the first peg.
                                #
                                next_peg = (peg + next_peg) % npegs

                                #
                                # Don't move to the same peg; that would be silly
                                #
                                if next_peg == peg:
                                    continue

                                #
                                # If the destination peg is empty, move there
                                #
                                if not len(pegs[next_peg]):
                                    pegs[peg].pop(0)
                                    pegs[next_peg].insert(0, value)
                                    moved_a_ring = True
                                    print("Moving value {} from peg {} to empty peg {}\n".format(value, peg + 1, next_peg + 1))
                                    break
                                elif value < pegs[next_peg][0]:
                                    #
                                    # Else if the destination peg has a lower value, move there
                                    #
                                    pegs[peg].pop(0)
                                    pegs[next_peg].insert(0, value)
                                    moved_a_ring = True
                                    print("Moving < value {} from peg {} to peg {} dest {}\n".format(value, peg + 1, next_peg + 1, pegs[next_peg][0]))
                                    break
                    if moved_a_ring:
                        break

                if not moved_a_ring:
                    print("Error, failed to move")
                    sys.exit(1)

            print_tower(pegs, nrings)

            #
            # Alternate between a) and b)
            #
            move_peg_one_right = not move_peg_one_right

        print("Finished pass\n")

nrings = 3
npegs = 3
solve_tower(nrings, npegs)
于 2021-03-13T11:22:35.317 に答える