Copyright (C) IOI日本委員会 1994. All rights reserved.


問題5.

この問題は、「ハノイの塔」として知られている。 3本の同じ太さの棒 A, B, C が地面に垂直に立っている。 A, B, C の棒が通るような穴が中央に開いている半径の異なる円盤が n 個ある。 n個の円盤には、1 から n までの相異なる番号が付いており、 番号の大きいほど半径は大きい。
最初は、A の棒に上から小さい順に重なっている。

図省略

次の (a), (b) のルールを満たしながら A に重なっている円盤を、すべて C に移したい。

(a) 1回に、A, B, C いずれかの棒の一番上にある円盤1枚だけを他の棒に移すことができる。

(b) どの棒においても、大きい円盤が小さい円盤の上にくることはない。

(a), (b) のルールを守りながら A にある円盤を C に移すには、どのようにすればよいか?
例えば、n=2 の場合

1回目 : Aの一番上の円盤(番号 1)をBに移す
2回目 : Aの一番上の円盤(番号 2)をCに移す
3回目 : Bの一番上の円盤(番号 1)をCに移す

が最も少ない回数の移動法である。

以下の3つの異なる言語で書かれたプログラムはどれも上記の問題の解を上の例のように 出力するものである。以下の問に答えよ。

[(1)] n=3 の場合、出力の5行目は

            5回目:[  (i)  ]  の一番上の円盤(番号[ (ii) ])を[ (iii) ] に移す
となる。それぞれの [ ] を埋めよ。 [2点]

[(2)] 以下の3つのプログラムのうち選択した言語について、空欄を埋めよ。 空欄には、一つの手続き、プロシージャ、あるいは関数、の呼び出しが入る。 [2点]


Cプログラム(5)


#include <stdio.h>

int count=0;
void move(int, char, char, char);

main()
{  
    move(3,'A','B','C');  exit(0); 
}

void move(int n, char a, char b, char c)
{  
    if (n<=0)
        return;
    move(n-1, a, c, b);
    printf("%3d回目: %cの一番上の円盤(番号%2d)を%cへ移す\n",
                    ++count, a, n, c);
    ------------------
   |     空欄箇所     |
    ------------------
}


QuickBASICプログラム(5)


DECLARE SUB move(n,A$,B$,C$)
DIM SHARED count AS INTEGER

    count=0
    CALL move(3,"A","B","C")
END

SUB move(n, A$, B$, C$)
    IF n>0 THEN
        CALL move(n-1,A$,C$,B$)
        count=count+1
        PRINT USING "###回目 @の一番上の円盤: "; count; A$;
        PRINT USING "(番号##)を @へ移す"; n; C$
         -----------------
        |    空欄箇所     |
         -----------------
    END IF
END SUB


Pascalプログラム(5)


PROGRAM test5;
VAR count : integer;

PROCEDURE move(n:integer; A,B,C:char);
BEGIN
    IF n>0 THEN 
    BEGIN
        move(n-1,A,C,B);
        count:=count+1;
        writeln(count:3,'回目: ', A, 
                'の一番の上の円盤(番号',n:2, ')を', C, 'へ移す');
         -----------------
        |    空欄箇所     |
         -----------------
    END
END;

BEGIN
    count:=0;
    move(3,'A','B','C')
END.


JOI'94へ戻る

JOIホームページへ戻る