分治:

203 阅读2分钟

分治(divide and conquer),全称分而治之,是一种非常重要且常见的算法策略。分治通常基于递归实现,包括“分”和“治”两个步骤。

  1. 分(划分阶段) :递归地将原问题分解为两个或多个子问题,直至到达最小子问题时终止。
  2. 治(合并阶段) :从已知解的最小子问题开始,从底至顶地将子问题的解进行合并,从而构建出原问题的解。

如图 12-1 所示,“归并排序”是分治策略的典型应用之一。

  1. :递归地将原数组(原问题)划分为两个子数组(子问题),直到子数组只剩一个元素(最小子问题)。
  2. :从底至顶地将有序的子数组(子问题的解)进行合并,从而得到有序的原数组(原问题的解)。

如何判断分治问题

一个问题是否适合使用分治解决,通常可以参考以下几个判断依据。

  1. 问题可以分解:原问题可以分解成规模更小、类似的子问题,以及能够以相同方式递归地进行划分。
  2. 子问题是独立的:子问题之间没有重叠,互不依赖,可以独立解决。
  3. 子问题的解可以合并:原问题的解通过合并子问题的解得来。

显然,归并排序满足以上三个判断依据。

  1. 问题可以分解:递归地将数组(原问题)划分为两个子数组(子问题)。
  2. 子问题是独立的:每个子数组都可以独立地进行排序(子问题可以独立进行求解)。
  3. 子问题的解可以合并:两个有序子数组(子问题的解)可以合并为一个有序数组(原问题的解)

第一题:汉诺塔

def hannuota(n:int):
    #f(1)=1   f(2)=3  f(3)=7  f(4)=15
    if n ==1:
        return 1
    else:
        return 2*hannuota(n-1)+1
if __name__ == '__main__':
    n=64
    print(hannuota(n))

    ###print(2**64-1) 居然是幂次方关系。。。。。。学到了!!

第二题:汉诺塔2

def hannuota(n,a,b,c): #n代表当前移动盘子数量
    global sum
    #f(1)=1   f(2)=3  f(3)=7  f(4)=15
    if n == 1:
        sum+=1
        if sum == M:
            print(f"#{n}: {a}->{c}") #n代表当前移动的盘子
    else:
        hannuota(n-1,a,c,b)
        sum += 1
        if sum == M:
            print(f"#{n}: {a}->{c}")
        hannuota(n - 1, b, a, c)
if __name__ == '__main__':
    N,M=map(int,input().split())
    sum = 0
    hannuota(N,"A",'B','C')
    print(sum)