8.6 分治法 ——【汉诺塔问题】

题目描述

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

有三根杆子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行输出一个整数,表示最少移动步数。

输入输出样例

输入:

3 2

输出:

#2: A->B
7



最终代码

1. c/c++ 【递归】

#include<bits/stdc++.h>
using namespace std;
int sum = 0, m;

void hanoi(char x,char y,char z,int n)
{
    //m是第几步,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. c/c++ 【栈,不推荐】

#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;
}



2. java




3. python




过程理解

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你说的白是什么白_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值