OCAC暑期比赛第二场 J题 汉诺塔 题解

汉诺塔
【题目描述】
汉诺塔是根据一个印度传说形成的数学问题:有三根杆子A, B, C, A杆上有n个穿孔圆盘, 盘的尺寸由下到上依次变小。
要求按照下列规则将所有圆盘移至C杆:
      1. 每次只能移动一个圆盘
      2. 大盘不能叠在小盘上面
找出最少需要移动多少次, 并打印移动的方案。
【输入格式】
一个整数n(1<=n<=15), 表示A杆最初有多少个圆盘。
【输出格式】
第一行, 输出最少移动的次数。
以下每行分别打印一次移动(例如, 移动A杆最上面的圆盘到C杆, 则输出"Move A to C")。
【样例输入】
3
【样例输出】
7
Move A to C
Move A to B
Move C to B
Move A to C
Move B to A
Move B to C
Move A to C
【题目分析】
本题涉及算法:递归。
我们开一个函数 dfs(char A, char B, char C, int n) ,
表示:将 n 个圆盘从 A 经由 B 移动到 C。
那么,当 n==1 时,我们直接输出 “Move A to C” 就可以了。
当 n > 1 时,我们可以这么想:
如果我要将最大的那个圆盘从 A 移动到 C ,那么我们需要先将其它 n-1 个圆盘从 A (经由 C )移动到 B,然后输出 “Move A to C” ,然后将在 B 上的 n-1 个圆盘从 B (经由 A )移动到 C 。
所以 dfs(char A, char B, char C, int n) 的实现的伪代码(伪代码就是那种不完全符合某个语言的语法,但是您能够看懂的语法;就好像虽然汪老师是湖州的但是还是能够听懂杭州话一样)如下:
dfs(A, B, C, n):
    if n==0 then 输出"Move ".A." to ".C
    else:
        dfs(A, C, B, n-1)
        输出"Move".A." to ".C
        dfs(B, A, C, n-1)
实现代码如下:

#include <bits/stdc++.h>
using namespace std;

void output(char A, char B) {
    printf("Move %c to %c\n", A, B);
}

void mov(char A, char B, char C, int n) { // A¾­¹ýBÒƶ¯µ½C
    if (n == 1) output(A, C);
    else {
        mov(A, C, B, n-1);
        output(A, C);
        mov(B, A, C, n-1);
    }
}

int n, ans;

int main() {
    cin >> n;
    ans = 1;
    for (int i = 2; i <= n; i ++) ans = ans * 2 + 1;
    cout << ans << endl;
    mov('A', 'B', 'C', n);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ocac/p/11131671.html
今日推荐