青蛙跳台阶:
问题描述:
(1)一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级。求该青蛙跳上一个n 级的台阶总共有多少种跳法。
(2)一只青蛙一次可以跳上1级台阶,也可以跳上2 级……它也可以跳上n 级,此时该青蛙跳上一个n级的台阶总共有多少种跳法?
分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,已便各个击破,分而治之。
思路:
假设:用 f(n) 表示青蛙跳上n阶台阶的跳法数。
对于问题(1)青蛙在跳上第n个台阶之前,因为青蛙只能跳1级台阶或者是2级台阶,所以只有两种情况,即一是青蛙在第n-1个台阶上;二是青蛙在第n-2个台阶上。
则 f(n)= f(n-1)+ f(n-2)。递归结束的条件为为 f(1)= 1;以及 f(2)=2。
python代码如下:
def fogjump(n):
if n == 1 or n == 0:
return 1
if n == 2:
return 2
if n > 2:
return fogjump(n-1) + fogjump(n-2)
if __name__ == "__main__":
print(fogjump(5))
对于问题(2),青蛙在上第n哥台阶之前,因为青蛙可以跳 1~n 级,所以有n种情况。青蛙在第n-1个台阶上;青蛙在第n-2个台阶上;青蛙在第n-3个台阶上......;青蛙在第2个台阶上;青蛙在第1个台阶上上。
则 f(n) = f(n-1) + f(n-2) + f(n-3) +......f(2)+f(1)
又f(n-1) = f(n-2) + f(n-3) +......f(2)+f(1)
两式相减,得递归式为:f(n) = 2*f(n-1)
递归结束的条件为为 f(1)= 1。
python代码如下:
def fogjump(n):
if n == 1 or n == 0:
return 1
if n > 1:
return 2*fogjump(n-1)
if __name__ == "__main__":
print(fogjump(5))
整数划分问题 :
问题描述:
将正整数 n 表示成一系列正整数之和,即 n = n1 + n2 + ......+nk (其中n1 >= n2>=...>=nk>=1,k >=1)。正整数 n 的这种表示称为正整数 n 的划分。正整数 n 的不同划分个数称为正整数 n 的划分数,记做 p(n)。
例如:正整数 6 有如下11种不同的划分,所以 p(6) = 11
6;
5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1。
在正整数 n 的所有划分中,将不大于 m 的划分个数记为 p(n, m),其中 m 为最大加数。
根据n和m的关系,考虑以下几种情况: 建立 p(n, m) 的如下递归关系。
(1)当 m = 1 时,p(n, 1) = 1 , n >=1。当最大加数为 1 时,任何正整数 n 只有一种划分形式,即 n = 1 +1 +1+......+1;
(2)当n=1 时,p(1,m) = 1,不论m的值为多少(m>0),只有一种划分,即{1};
(3)当 n < m 时,p(n, m) = p (n, n) 。 最大加数不能大于n,划分中不可能出现负数,因此就相当于p(n,n)
(4) 当 n=m 时,根据划分中是否包含最大加数n,可以分为两种情况:
(a). 划分中包含最大加数n的情况,只有1个,即{n};
(b). 划分中不包含最大加数n的情况,这时划分中最大的加数一定比n小,即 n 的所有 (n-1) 划分。
因此 p(n, n) =1 + p(n, n-1);
(5) 当 n>m 时,根据划分中是否包含最大加数m,可以分为两种情况:
(a). 划分中包含最大加数m的情况,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi} 的和为 n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分的个数为 p(n-m, m);
(b). 划分中不包含最大加数m的情况,则划分中所有值都比 m 小,即 n 的 (m-1) 划分,个数为 p(n,m-1);
因此 p(n, m) = p(n-m, m) + p(n, m-1);
综合以上情况,我们可以看出,上面的结论具有递归定义特征,其中(1)和(2)属于递归结束条件,(3)和(4)属于特殊情况,将会转换为情况(5)。而情况(5)为通用情况,属于递推的方法,其本质主要是通过减小m以达到递归结束条件,从而解决问题。其递推表达式如下:
python代码实现如下:
def divide(n, m):
if (n == 1) or (m == 1):
return 1
if n < m:
return divide(n, n)
if n == m:
return divide(n, n-1) + 1
if n > m > 1:
return divide(n, m-1) + divide(n-m, m)
if __name__ == '__main__':
a = int(input())
print(divide(a, a))