【蓝桥】汉诺塔

题目

题目描述

汉诺塔是一个古老的数学问题:

有三根杆子A,B,C。A 杆上有 n 个 (n>1) 穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至 C 杆:

  • 每次只能移动一个圆盘;
  • 大盘不能叠在小盘上面。

提示:

可将圆盘临时置于 B 杆,也可将从 A 杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。问:如何移?最少要移动多少次?

输入描述

一行,包含 2 个正整数,一个是 N,表示要移动的盘子数;一个是 M,表示最少移动步数的第M步。

输出描述

共 2 行。 第一行输出格式为:#No: a->b,表示第 M 步骤具体移动方法,其中 No 表示第 M 步移动的盘子的编号(N个盘子从上到下依次编号为 1 到 n),表示第M步是将 No 号盘子从 a 杆移动到 b 杆(a和 b 的取值均为 {A、B、C})。 第 2 行输出一个整数,表示最少移动步数。

输入输出样例

示例

输入

1
3 2

输出

1
2
#2: A->B
7

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

解题

源码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//递归版本
#include <iostream>
using namespace std;
int sum = 0, m;
void hanoi(char x,char y,char z,int n){
if(n==1) {
sum++;
if(sum==m) cout<<"#"<<n<<": "<<x<<"->"<<z<<endl;
}
else {
hanoi(x,z,y,n-1);
sum++;
if(sum==m) cout<<"#"<<n<<": "<<x<<"->"<<z<<endl;
hanoi(y,x,z,n-1);
}
}
int main(){
int n; cin>>n>>m;
hanoi('A','B','C',n);
cout<<sum<<endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//栈版本
#include<bits/stdc++.h>
using namespace std;
const int N = 30;
int sum = 0, m;
struct mystack{
int a[N]; //存放栈元素
int t = -1; //栈顶位置
void push(int x){ a[++t] = x; } //把x送入栈
int top() { return a[t]; } //返回栈顶元素
void pop() { t--; } //弹出栈顶
int empty() { return t==0?1:0;} //返回1表示空
}st[4]; //定义三个柱子,不用st[0]

void move(int x, int y,int n){ //移动圆盘
int element = st[x].top(); //从杆子x上取出顶部的圆盘放到杆子y上
st[x].pop();
st[y].push(element);
sum++;

char a,b; //用于打印
if(x==1) a='A'; if(x==2) a='B'; if(x==3) a='C';
if(y==1) b='A'; if(y==2) b='B'; if(y==3) b='C';
if(sum == m) cout<<"#"<<n<<": "<<a<<"->"<<b<<endl;
}
void hanoi(int n, int x, int y, int z){
if(n==1) move(x,z,n);
else{
hanoi(n-1, x, z, y);
move(x,z,n);
hanoi(n-1, y, x, z);
}
}
int main(){
int n; cin>>n>>m;
for(int i=n;i>=1;i--) //初始状态:在第1个杆子上添加n个圆盘
st[1].push(i);
hanoi(n,1,2,3);
cout<<sum<<endl;
return 0;
}

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
n, m = map(int, input().split())
sum = 0
def hanoi(x, y, z, n):
global sum
if (n == 1):
sum += 1
if (sum == m):
print(f"#{n}: {x}->{z}")
else:
hanoi(x, z, y, n-1)
sum += 1
if sum == m:
print(f"#{n}: {x}->{z}")
hanoi(y, x, z, n-1)

hanoi("A", "B", "C", n)
print(sum)

总结

C++版

  1. 其实就是递归,单步分解,具体分解过程看CSDN详细解答
1
2
3
4
5
6
7
8
9
10
//栈的原子操作
const int N = 100100; //定义栈的大小
struct mystack{
int a[N]; //存放栈元素
int t = -1; //栈顶位置
void push(int x){ a[++t] = x; } //送入栈
int top() { return a[t]; } //返回栈顶元素
void pop() { t--; } //弹出栈顶
int empty() { return t==0?1:0;} //返回1表示空
};

Python版

  1. 原理一样,都是递归单步分解