汉诺塔之添加移动编号

目录

前言

方法一:(简单粗暴)

方法二:(简化上面的思路)

后记


前言

代码风格不好,也是第一次写博客,还请大佬们谅解,有简便写法希望不吝赐教

搜了很久发现大佬们汉诺塔写的都很好,也清楚,但是有一道题要求把编号也打印出来,没有搜到对应的博客,所以写了此篇。

 方法一:(简单粗暴)

首先定义,hanoit(int num, char a, charb, char c)表示将num个盘子从a经过b移动到c

move(char a, char c)表示将a最上面的盘子移动到c

每次只是移动最上面的,所以也就保证了,移动是符合规则的。

代码和注释写的应该比较直观了,get()函数写的比较复杂了,但是其实道理很简单

#include<stdio.h>

int cnt = 0, no;
struct n{
    int idx[25]; //存放这个柱子从下到上的盘子, i = 1 开始存放
    int tot; //存放有多少个盘子
}A, B, C;

int get(char src, char des){
    if(src == 'A'){
        if(des == 'B'){
            B.tot++; //B上面增加一个
            B.idx[B.tot] = A.idx[A.tot]; //B增加的是A最上面的
            A.tot--; // A减少一个
        }
        else if(des == 'C'){
            C.tot++;
            C.idx[C.tot] = A.idx[A.tot];
            A.tot--;
        }
        return A.idx[A.tot+1]; // 返回A最上面的是几号盘子
    }
    else if(src == 'B'){
        if(des == 'A'){
            A.tot++;
            A.idx[A.tot] = B.idx[B.tot];
            B.tot--;
        }
        else if(des == 'C'){
            C.tot++;
            C.idx[C.tot] = B.idx[B.tot];
            B.tot--;
        }
        return B.idx[B.tot+1];
    }
    else{
        if(des == 'A'){
            A.tot++;
            A.idx[A.tot] = C.idx[C.tot];
            C.tot--;
        }
        else if(des == 'B'){
            B.tot++;
            B.idx[B.tot] = C.idx[C.tot];
            C.tot--;
        }
        return C.idx[C.tot+1];
    }
}
void move(char a, char c){ // 将a此时最上面的盘子移动到c
    cnt ++;
    no = get(a, c); // a最上面的是什么
    printf("step #%d: move %d from %c to %c\n", cnt, no, a, c);
}
void hanoit(int num, char a, char b, char c){
    if(num == 1) move(a, c); // 如果只需要移动一个盘子,直接移动即可
    else{
        hanoit(num-1, a, c, b); //先将a从最上面开始数的num-1个盘子经过c移动到b
        move(a, c); // a只剩下最下面的一个盘子了,直接移动
        hanoit(num-1, b, a, c); // 回到原问题,将b的num-1个盘子经过a移动到c,结束
    }
}
int main(){
    int n;
    scanf("%d", &n);
    no = n;
    //初始化
    for(int i = 1; i <= n; i++){
        A.idx[i] = i;
        B.idx[i] = 0;
        C.idx[i] = 0;
    }
    A.tot = n;
    B.tot = 0;
    C.tot = 0;
    hanoit(n, 'A', 'B', 'C');
}

 方法二:(简化上面的思路)

首先定义,hanoit(int low, int high, char a, char b, char c)表示将a柱子从low编号到high编号的盘子,经过b移动到c.

move(int idx, char a, char c)表示将a柱子的idx编号的盘子移动到c.

#include<stdio.h>
int cnt = 0;

void move(int idx, char a, char c){
    cnt ++;
    printf("step #%d: move %d from %c to %c\n", cnt, idx, a, c);
}
void hanoit(int low, int high, char a, char b, char c){
    if(low == high) move(high, a, c); // 也就是只移动一个盘子的时候
    else{
        hanoit(low+1, high, a, c, b); // a保留最下面的盘子,上面的全部移动到b
        move(low, a, c); //a最下面的盘子直接移动到c
        hanoit(low+1, high, b, a, c); // 回到原问题,将b柱子上所有柱子(从low+1到high)全部移动到c
    }
}
int main(){
    int n;
    scanf("%d", &n);
    hanoit(1, n, 'A', 'B', 'C');
}

后记

其实两种方法的时空效率接近,只是第二种方法看起来更简单一些。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值