44. 分治算法

发布时间 2023-07-11 17:37:34作者: 夏冰翎

一、什么是分治算法

  分治(Divide and Conquer)算法,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似问题的子问题,再把子问题分成更小的子问题 …… 直到最后子问题可以简单的直接求值,原问题的解即子问题的解的合并。

  分治法在每一层递归上都有三个步骤:

  1. 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
  2. 解决:若子问题规模较小而容易被解决则直接解。否则递归地解各个子问题;
  3. 合并:将各个子问题的解合并为原问题的解;

二、汉诺塔问题

  汉诺塔问题有三个柱子,在一个柱子上从下往上按照大小顺序摆放 64 片黄金圆盘。要求我们从下面开始按大小顺序重新摆放在另一哥柱子上。并且规定,在小圆盘上不能放大圆盘,在三个柱子之间一次只能移动一个圆盘。

  汉诺塔问题的解决思路:

  1. 先把上面的盘从 A 移动到 B;
  2. 将最下面的盘从 A 移动到 C;
  3. 在把 B 上的所有盘从 B 移动移动 C;
#include <stdio.h>

int main(void)
{
    HanoiTower(10,'a','b','c');

    return 0;
}
/**
 * @brief 汉诺塔问题
 * 
 * @param num 要移动的盘子个数
 * @param a 第一个柱子
 * @param b 第二个柱子
 * @param c 第三个柱子
 */
void HanoiTower(int num,char a,char b,char c)
{
    // 如果只有一个盘
    if(num == 1)
    {
        printf("第 1 个盘从 %c → %c\n",a,c);
    }
    else
    {
        // 如果 n>=2,我们总是可以看做两个盘,最下边的一个盘和上面的所有盘
        // 1. 把上面的盘 a→b,移动过程会使用c
        HanoiTower(num-1,a,c,b);
        // 2. 把最下面的盘 b→c
        printf("第 %d 个盘从 %c → %c\n",num,a,c);
        // 3. 把b中所有的盘 b→c,移动过程会使用C
        HanoiTower(num-1,b,a,c);
    }
}