个盘子的汉诺塔需要移动几步_[W2D1]汉诺塔问题

5ad3070403a62d7c8dec5622cc6947bb.png

第二周我们开始解决一些经典的递归问题

  • 题目链接:【经典】汉诺塔问题 - 题目 - 青藤 OJ
  • 题目来源:经典题目

题目大意

非常经典的汉诺塔问题。

这题要求输入

,表示 A 柱子上有 n 个圆盘。现在需要移动到 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 

解法

首先汉诺塔问题大家应该非常熟悉了。

数量上来说

所以

是公比为 2 的等比数列,首项为
,所以

所以第一个小问题就很容易解决了

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

int main(){
	int n;
	scanf("%d",&n);
	//<< 在位运算里面是左移,不熟悉的话可以for循环求2^n 
	printf("%dn",(1<<n)-1);
	//输出把 n 个盘子从 'A' 借助 'B' 移到 'C' 的解决方案  
	hanoi(n,'A','B','C'); 
	return 0;
}

现在我们的关键就是怎么解决这个 hanoi(n,'A','B','C');

做递归类问题的核心就两点:

  • 边界情况特别处理
  • 假装这个函数的功能已经完成了,用这个函数实现这个函数(用魔法打败魔法)

按照这两个思路,我们可以写出下面的标程

#include <bits/stdc++.h>
using namespace std;
void hanoi(int n, char x, char y, char z) {
    //要把 n 个盘子从 x 通过 y 移到 z
    //边界情况
    if (n == 1) {
        //直接从 x 移到 z
        printf("Move %c to %cn", x, z);
        return;
    }
    //先把 n-1 个从 x 移到 y
    hanoi(n - 1, x, z, y);
    //把第 n 个从 x 直接移到 z
    printf("Move %c to %cn", x, z);
    //再把那 n-1 个从 y 移到 z
    hanoi(n - 1, y, x, z);
}
int main() {
    int n;
    scanf("%d", &n);
    //<< 在位运算里面是左移,不熟悉的话可以for循环求2^n
    printf("%dn", (1 << n) - 1);
    //把 n 个盘子从 'A' 借助 'B' 移到 'C'
    hanoi(n, 'A', 'B', 'C');
    return 0;
}

去掉注释,其实很短

#include <bits/stdc++.h>
using namespace std;
void hanoi(int n, char x, char y, char z) {
    if (n == 1) {
        printf("Move %c to %cn", x, z);
        return;
    }
    hanoi(n - 1, x, z, y);
    printf("Move %c to %cn", x, z);
    hanoi(n - 1, y, x, z);
}
int main() {
    int n;
    scanf("%d", &n);
    printf("%dn", (1 << n) - 1);
    hanoi(n, 'A', 'B', 'C');
    return 0;
}

用递归的方法写程序就是这么简单、巧妙、且短小精悍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值