CCF 2024年 CSP-J代码填空题-汉诺塔问题

传送门:https://ti.luogu.com.cn/problemset/1043

第 2 题
(汉诺塔问题) 给定三根柱子,分别标记为 A、B 和 C。初始状态下,柱子 A 上有若干个圆盘,这些圆盘从上到下按从小到大的顺序排列。任务是将这些圆盘全部移到柱子 C 上,且必须保持原有顺序不变。在移动过程中,需要遵守以下规则:

只能从一根柱子的顶部取出圆盘,并将其放入另一根柱子的顶部。
每次只能移动一个圆盘。
小圆盘必须始终在大圆盘之上。
试补全程序。

include

include

using namespace std;

void move(char src, char tgt) {
cout << "从柱子" << src << "挪到柱子" << tgt << endl;
}

void dfs(int i, char src, char tmp, char tgt) {
if (i == ) {
move(;
return;
}
dfs(i - 1, );
move(src, tgt);
dfs(, );
}

int main() {
int n;
cin >> n;
dfs(n, 'A', 'B', 'C');
}
① 处应填( )
A. 0
B. 1
C. 2
D. 3
② 处应填( )
A. src, tmp
B. src, tgt
C. tmp, tgt
D. tgt, tmp
③ 处应填( )
A. src, tmp, tgt
B. src, tgt, tmp
C. tgt, tmp, src
D. tgt, src, tmp
④ 处应填( )
A. src, tmp, tgt
B. tmp, src, tgt
C. src, tgt, tmp
D. tgt, src, tmp
⑤ 处应填( )
A. 0
B. 1
C. i - 1
D. i
1.
A. 0
B. 1
C. 2
D. 3
2.
A. src, tmp
B. src, tgt
C. tmp, tgt
D. tgt, tmp
3.
A. src, tmp, tgt
B. src, tgt, tmp
C. tgt, tmp, src
D. tgt, src, tmp
4.
A. src, tmp, tgt
B. tmp, src, tgt
C. src, tgt, tmp
D. tgt, src, tmp
5.
A. 0
B. 1
C. i - 1
D. i

我们来逐步分析这个汉诺塔的递归模板:


递归核心逻辑

dfs(i, src, tmp, tgt) 表示:
i 个盘子src 移到 tgt,借助 tmp

  • 如果 i == 1:直接把一个盘子从 src 移到 tgt

  • 否则:

    1. 先把 i-1 个盘子从 src 移到 tmp(借助 tgt)。
    2. 再把最大的盘子从 src 移到 tgt
    3. 最后把 i-1 个盘子从 tmp 移到 tgt(借助 src)。

填空解析

递归出口条件:当只剩一个盘子时,直接移动。
👉 填 1
答案:B

递归出口的 move 调用:应该把唯一的盘子从 src 移到 tgt
👉 填 src, tgt
答案:B

第一次递归:把 i-1 个盘子从 src 移到 tmp,借助 tgt
👉 填 src, tgt, tmp
答案:B

第二次递归:把 i-1 个盘子从 tmp 移到 tgt,借助 src
👉 填 tmp, src, tgt
答案:B

第二次递归的参数:移动的是 i-1 个盘子。
👉 填 i - 1
答案:C


最终答案

  1. ① B
  2. ② B
  3. ③ B
  4. ④ B
  5. ⑤ C

✅ 补全后的代码如下:

#include <iostream>
using namespace std;

void move(char src, char tgt) {
    cout << "从柱子" << src << "挪到柱子" << tgt << endl;
}

void dfs(int i, char src, char tmp, char tgt) {
    if (i == 1) { // ①
        move(src, tgt); // ②
        return;
    }
    dfs(i - 1, src, tgt, tmp); // ③
    move(src, tgt);
    dfs(i - 1, tmp, src, tgt); // ④ ⑤
}

int main() {
    int n;
    cin >> n;
    dfs(n, 'A', 'B', 'C');
}

好的 👍
我们来画出 3 层汉诺塔 (dfs(3, 'A','B','C')) 的 递归展开树 + 移动顺序


🌲 递归展开树(dfs 调用)

dfs(3, A, B, C)
│
├─ dfs(2, A, C, B)     // Step1: 先把上面 2 个从 A 移到 B
│   │
│   ├─ dfs(1, A, B, C)   → Move A → C
│   ├─ Move A → B
│   └─ dfs(1, C, A, B)   → Move C → B
│
├─ Move A → C          // Step2: 把最大的从 A 移到 C
│
└─ dfs(2, B, A, C)     // Step3: 再把 2 个从 B 移到 C
    │
    ├─ dfs(1, B, C, A)   → Move B → A
    ├─ Move B → C
    └─ dfs(1, A, B, C)   → Move A → C

📜 实际移动顺序(执行的 move 调用)

  1. A → C
  2. A → B
  3. C → B
  4. A → C
  5. B → A
  6. B → C
  7. A → C

🔎 图示说明(3 层汉诺塔过程)

初始: A:[3,2,1], B:[], C:[]

Step1: A → C    A:[3,2], B:[], C:[1]
Step2: A → B    A:[3],   B:[2], C:[1]
Step3: C → B    A:[3],   B:[2,1], C:[]
Step4: A → C    A:[],    B:[2,1], C:[3]
Step5: B → A    A:[1],   B:[2],   C:[3]
Step6: B → C    A:[1],   B:[],    C:[3,2]
Step7: A → C    A:[],    B:[],    C:[3,2,1]

最终:全部移到 C


更多汉诺塔问题C++学习:https://www.bilibili.com/video/BV1ZY411g725/?spm_id_from=333.337.search-card.all.click&vd_source=7e76470841b91c692454adc02ed9ccf1

posted @ 2025-08-27 10:54  kkman2000  阅读(28)  评论(0)    收藏  举报