汉诺塔问题求解

218 阅读2分钟

思路:

    现有起始串x、过渡串y和目标串z,盘子数量n
    最大盘上面的所有盘记为 □
        (如一共五个盘子,前四个小的盘子记为 □
        
    步骤:
        1. □ → 过渡串y       (这样才能移动最大盘)
        2. 最大盘 → 目标串z
        3. □ → 目标串z
        
    而步骤1如何实现呢?
    其实步骤1又成为了一个新的问题:n-1层的汉诺塔如何操作,
    但是还是继续上面的步骤来操作,直到为1层,就可以直接移动。这些分解出的小问题实现后,大问题自然就实现了(大问题由小问题组合而成)
    只不过在这个过程中,起始串、过渡串、目标串的位置会改变,如:
        最初的步骤1. □ → 过渡串y,此步骤的目标串z为大整体的过渡串y
        

代码(C语言)

#include <stdio.h>
int hanoi(int n, char x, char y, char z);
int move(int n, char start, char end);
/*
	汉诺塔
*/
#include <stdio.h>
int main()
{
    int n, counter;
    printf("Input the number of diskes:");
    scanf_s("%d", &n);      //n:盘子数量
    printf("\n");
    counter = hanoi(n, 'A', 'B', 'C');
    return 0;
}
int hanoi(int n, char x, char y, char z)//x、y、z永远代表着起始、过渡、目标
{
    if (n == 1)
        move(1, x, z);  //起始x → 目标z
    else
    {
        hanoi(n - 1, x, z, y);  // 此处的过渡为 □ 的目标
        move(n, x, z);          //最大盘:x → z   (起始→目标)
        hanoi(n - 1, y, x, z);  // □:y → z  (过渡→目标)
    }
    return 0;
}

//移动
int move(int n, char start, char end)
{
    static int k = 1;
    printf("步骤%d(盘子%d):  %c->%c\n", k, n, start, end);
    if (k++ % 3 == 0)
        printf("\n");
    return 0;
}

代码(python)

def hann(x, y, z, n):  		 #x起始,y过渡,z目标,要从x->z
    if n == 1:        			 #若为一层,直接起始->目标
        print("{}->{}".format(x,z))
    else:               			 #每层都是三步,修改改变的只是起始、过渡和目标(小问题的目标基于大问题是步骤几)
        hann(x, z, y, n-1)          		 #总步骤1.x->y(起始->过渡),本层的过渡是n-1层的目标(把 □ 挪走)
        print("{}->{}".format(x,z)) 	 #总步骤2.x->z(起始->目标)(剩最大盘移到目标)
        hann(y, x, z, n-1)          		 #总步骤3.y->z(过渡->目标)(把 □ 放上)
n = eval(input("多少个圆盘:"))
hann("A", "B", "C", n)