具体所使用的方法可参考Turing的《python数据结构与算法分析》或搜索其他资料文章。
整数规划
思路:
q(n,m)表示对n进行整数划分,但所有加数<=m。
将正整数n表示成一系列正整数之和:n = n1 + n2 + … + nk,其中n1 ≥ n2 ≥ … ≥ nk ≥ 1,(k ≥ 1)。正整数n的这种表示称为正整数n的划分。
把n的整数划分记为“加数小于或等于某个数的划分”,在这里把这个“某个数”记为m。我们将划分的种类数记为q(n,m)。
q(n, m)计算分析过程如下:
- 当n=1时,q(1,m):表示是对1的划分,那么只有一种划分方式{1};当m=1时,q(n,1):表示所有加数均小于等于1;所以当n == 1或m=1时,划分种类数都为1。
- 当1 < m <n时,所有的加数均小于等于m,分为所有的整数划分中加数包含m和所有的整数划分中加数不包含m两种情况。当包含m时,划分为{m + …}种类数为q(n-m, m);当不包含m时,所以加数均小于等于m-1,所以划分数为q(n, m-1)。故这种情况下划分种类数为q(n-m, m) + q(n, m-1)。
- 当n=m时,若划分出来的数包含n,那只有一种方式,即{n};若划分出来的数不包含n,就可以认为划分出来的数都小于n,即小于等于n-1。故这种情况下划分种类数为1+q(n,n-1)。
- 当n < m时,和n=m情况相同,故这种情况下划分种类数为q(n,n)。
# 整数规划
def q(n, m):
if n == 1 or m == 1:
return 1
elif n < m:
return q(n, n)
elif n == m:
return 1 + q(n, m-1)
else:
return q(n-m, m) + q(n, m-1)
n = int(input('n = '))
m = int(input('m = '))
print(q(n, m))
结果截图:
汉诺塔
问题:n个大小不同的圆盘(编号记为1,2,…,n)按尺寸大小(大在下,小在上)叠放在3根杆(编号为A、B、C)的A号杆上,每次移动一个盘,将这n个盘A号杆移动到C号杆,移动过程中不允许大盘叠放在小盘之上,求解最少的移动步骤。
思路:
- 当n=1时,则只需移动一次。
- 当n>1时
- 借助目标杆(C)将前n-1个盘从源杆(A)移动到过度杆(B);
- 将源杆(A)上最后一个盘子移动到目标杆(C);
- 借助源杆(A),将过度杆(B)上的n-1个盘移动到目标杆(C)上。
count = 0
def move(n, M, N):
global count
count = count + 1
print('第' + str(count) +'次:' + str(n) + '号圆盘:' + str(M) + '->' + str(N)) # 如果需要输入移动过程则打印这些内容
def hanoi(n, A, B, C):
if n == 1:
move(1, A, C)
else:
hanoi(n-1, A, C, B)
move(n, A, C)
hanoi(n-1, B, A, C)