这是一个对“上台阶问题”的分析,即有N个台阶,每次最多跨M个台阶,有多少种走法数。首先声明,作者非专业研究算法,之所以想这个问题,是因为02年左右初二的时候被拉去参加一个初中数学竞赛,最后一道题目就是N=10,M=2时候的“上台阶问题”,当时差点一个个去穷举了……所以幼小的心灵留下了深刻的印象,最近偶有所感,又仔细分析了一下,有些感想来和大家分享。

M=2时候特例分析

对于N个台阶的走法数F(N),考虑第一步的情况:第一步跨1个台阶,剩下N-1个台阶走法为F(N-1);第一步跨2个台阶,剩下N-2个台阶走法为F(N-2)。故F(N)=F(N-1) + F(N-2),即为斐波那契数列。

还可以考虑另一种方法:对于N个台阶,记M(N,k)表示N个台阶,其中有且仅有K次跨2个台阶的走法数。考虑扩展情况下,K~(0,N),当K>[n/2]时候,M(N,k)=0。针对跨2个台阶的数目,对N个台阶的走法数进行划分,有F(N) = M(N,0) + M(N,1) + M(N,2) + … + M(N,N)

在考虑M(N,k),即N个台阶有且仅有k次跨2个台阶的走法数。针对最后一次跨2个台阶的位置,对M(N,k)进行划分。有M(N,k) = M(N-2,k-1) + M(N-3,k-1) + M(N-4,k-1) + … + M(0,k-1),其中M(N-2,k-1)表示最后一次跨越台阶为N-1,N,此时前面N-2个台阶中必有K-1次跨2个台阶,即M(N-2,K-1)。

这样,当N为奇数时候,

F(N+2) - F(N+1) = {M(N+2,0) – M(N+1,0)} + {M (N+2,1) – M(N+1,1)} + … + { M(N+2, (N+1)/2) – M(N+1, (N+1)/2)}

其中M(N+2,K) – M(N+1,k) = {M(N,k-1) + M(N-1,k-1) + … + M(0,k-1)} – {M(N-1,k-1) + M(N-2,k-1) + … + M(0,k-1)} = M(N,k-1)

故F(N+2) – F(N+1) = M(N,0) + M(N,1) + M(N,2) + … + M(N,(N-1)/2) = F(N)

同理,当N为偶数时候,注意到M(N,N/2)=1,即N为偶数个台阶,其中有N/2次跨2个台阶,显然只有一种情况。此时同样有 F(N+2) – F(N+1) = F(N)。

对于N<=10的情况,M(N,k)值如下,其中K~(0-5),F(N)= M(N,0) + M(N,1) … +(N,5),对应斐波那契数列。

N

M(N,0)

M(N,1)

M(N,2)

M(N,3)

M(N,4)

M(N,5)

F(N)

10

1

9

28

35

15

1

89

9

1

8

21

20

5

0

55

8

1

7

15

10

1

0

34

7

1

6

10

4

0

0

21

6

1

5

6

1

0

0

13

5

1

4

3

0

0

0

8

4

1

3

1

0

0

0

5

3

1

2

0

0

0

0

3

2

1

1

0

0

0

0

2

1

1

0

0

0

0

0

1

通式分析

进一步扩展,N个台阶,每一次最多跨M个台阶,记L(N,M)为对应的走法数,显然N>=M。可以看出,这个问题具有下面两个性质:

当M=N时候,除去一次跨N个台阶情况,有L(N,N) = 1+ L(N,N-1).

当M

有以上两个性质,加上初始值M(0,0) = 0,就可以递推出任何L(N-M,M)。其中,斐波那契数列为M=2时候的特例。

Python的实现

这只是一个实例代码,在Win7中用自带的IDLE写的,没有考虑复杂度,并且限定最大台阶数为20。因为使用格式化字符串,运行时候,要注意终端的大小。之所以使用Izanagi.py,是因为这个单词据说是“伊邪那岐”,比Fibonacci的斐波那契霸气些。遇到单词拼写和语法错误,请自动忽略……

首先是一个自定义的异常类,主要处理非法最大台阶数,即台阶数目不是整数、台阶数目不在限定范围(设定为1-20)。

1 #!/usr/bin/env python

2 #-*- coding: utf-8 -*-

3

4 classCommonException(Exception):5 """

6 Base Exception7 """

8 message = "An exceptin occured."

9

10 def __init__(self, **kwargs):11 try:12 self._error_str = self.message %kwargs13 exceptException:14 self._error_str =self.message15

16 def __str__(self):17 returnself._error_str18

19 classIntegerError(CommonException):20 """

21 Not an integer22 """

23 message = "Exception: %(number)s is not an integer!"

24

25 classRangeError(CommonException):26 """

27 integer range error28 """

29 message = "Exception: %(number)s is not in the range!"

30

31 if __name__ == "__main__":32 try:33 raise IntegerError(number = -1)34 exceptException,e:35 printstr(e)36

37 try:38 raise RangeError(number = 10000)39 exceptException,e:40 print str(e)

自定义异常类

接下来是主程序,见代码。其中两个函数help和result直接使用字符串输出了。

1 #!/usr/bin/env python

2 #-*- coding: utf-8 -*-

3

4 from __future__ importdivision5 from lzanagi_exception importIntegerError,RangeError6

7 classLzanagi():8 def __init__(self, STAIR):9 self.STAIR =STAIR10 self.MAXSTEP = 20

11 self.HEAD = 10

12 self.LINE = 10

13 self.MATRIX =[]14 self.RATIO =[]15 self.init_table()16

17 definit_table(self):18 """

19 set the MATRIX[0][0] to get the MATRIX[1][1] by using the uniform format for loop20 """

21 if type(self.STAIR) != type(1):22 raise IntegerError(number =self.STAIR)23 if self.STAIR < 0 or self.STAIR >self.MAXSTEP:24 raise RangeError(number =self.STAIR)25 self.MATRIX =[]26 for i in range(self.STAIR + 1):27 matrix_array =[]28 ratio_array =[]29 for j in range(self.STAIR + 1):30 matrix_array.append(0)31 ratio_array.append(1)32 self.MATRIX.append(matrix_array)33 self.RATIO.append(ratio_array)34

35 defbegin_lzanagi(self):36 """

37 Note the the MATRIX is consistent of many lines,each line contain38 one stair and many step values.39 When calculate, begin with min step to max step.40 What you get is MATRIX[stair][step]41 """

42 for step in range(1, self.STAIR+1):43 for stair in range(1, self.STAIR+1):44 if stair <45 self.matrix elif step="=stair:47">

48 else:49 #when step = 1, then self.MATRIX[stair][1]= self.MATRIX[stair-1][1]=1

50 #when step = 2, then self.MATRIX[stair][step] = self.MATRIX[stair-1][step] + self.MATRIX[stair-2][step]

51 #when step = 3, then self.MATRIX[stair][step] = self.MATRIX[stair-1][step] + self.MATRIX[stair-2][step] + self.MATRIX[stair-3][step]

52 #...

53 #until step = MAXSTEP, finish lzanagi!

54 for i in range(1, step+1):55 self.MATRIX[stair][step] += self.MATRIX[stair-i][step]56

57 defcalculate_ratio(self):58 for step in range(1, self.STAIR+1):59 for stair in range(2, self.STAIR+1):60 self.RATIO[stair][step] = round(self.MATRIX[stair][step]/self.MATRIX[stair-1][step],4)61

62 defprint_head(self):63 string = "{0:%d}" %self.HEAD64 string = string.format("STAIR\\STEP")65 line = "{0:>%d}" %self.LINE66 for i inrange(self.STAIR):67 string += line.format(i+1)68 printstring69

70 defprint_line(self, table, index):71 string = "{0:^%d}" %self.HEAD72 string = string.format("STAIR_"+str(index))73 line = "{0:>%d}" %self.LINE74 for i in range(1,self.STAIR + 1):75 string +=line.format(table[index][i] )76 printstring77

78 defprint_number(self):79 self.print_table(self.MATRIX)80

81 defprint_ratio(self):82 self.print_table(self.RATIO)83

84 defget_one_ratio(self, index):85 """

86 when index is 2, this is the Fibonacci87 """

88 result =[]89 for i in range(1, self.STAIR+1):90 result.append(self.RATIO[i][index])91 returnresult92

93 defprint_table(self, table):94 self.print_head()95 for i in range(self.STAIR ,0 ,-1):96 self.print_line(table, i)97

98 @staticmethod99 defhelp():100 string = '''

101 You must input an integer, and in the range 1~ MAXSTAIR.102 Note that I doesn't consider the time complexity. So I just limit the MAXSTAIR to 20103

104 The is the "step stair question".105 for example:106 10 stairs,you can take one or two step(s) at once,so you get the Fibonacci!107 More over, 10 stairs,but you can take one or two or three step(s) at once,what will happen?108 Generally, N stairs,you can take at most M steps at once (Of course N>=M). Now what will happen?109 When M=2,you get Fibonacci. So more generally, I call this method Lzanagi!110 This program aims at this question. I can prove this algorithm,that is say,this problem can be resoved by this method.111 '''

112 printstring113

114 @staticmethod115 defresult():116 string = '''

117 You can see that S(N,N), which means that N stairs,you can take at most N step once, S(N,N) = 2^(N-1).118 This is an interesting thing!119 Proving: S(N,N) = 1 + S(N,N-1) = 1 + S(N-1,N-1) + S(N-2,N-1) + ... + S(1,N-1).120 Note that S(1,N-1) = S(1,1); S(2,N-1) = S(2,2); ...;S(N-2,N-1) = S(N-2,N-2).121 Then you can use the matheimatical induction to prove that S(N,N) = 1 + 2^(N-2) + 2^(N-3) + ... + 1 = 2^(N-1)122 '''

123 printstring124

125

126 if __name__ == "__main__":127 try:128 lzanagi = Lzanagi(10)129 print "Init Lzanagi!"

130 lzanagi.print_number()131 print "Begin Lzanagi!"

132 lzanagi.begin_lzanagi()133 print "The result is as follow:"

134 lzanagi.print_number()135 print "Calculate the ration!"

136 lzanagi.calculate_ratio()137 print "The ration is as follow:"

138 lzanagi.print_ratio()139 #lzanagi.help()

140 #lzanagi.result()

141 exceptException,e:142 printstr(e)143 Lzanagi.help()

主程序

结果简单分析

Init Lzanagi!

STAIR\STEP1 2 3 4 5 6 7 8 9 10STAIR_10 0 0 0 0 0 0 0 0 0 0

STAIR_9 0 0 0 0 0 0 0 0 0 0

STAIR_8 0 0 0 0 0 0 0 0 0 0

STAIR_7 0 0 0 0 0 0 0 0 0 0

STAIR_6 0 0 0 0 0 0 0 0 0 0

STAIR_5 0 0 0 0 0 0 0 0 0 0

STAIR_4 0 0 0 0 0 0 0 0 0 0

STAIR_3 0 0 0 0 0 0 0 0 0 0

STAIR_2 0 0 0 0 0 0 0 0 0 0

STAIR_1 0 0 0 0 0 0 0 0 0 0

Begin Lzanagi!

The resultisas follow:

STAIR\STEP1 2 3 4 5 6 7 8 9 10STAIR_101 89 274 401 464 492 504 509 511 512STAIR_91 55 149 208 236 248 253 255 256 256STAIR_81 34 81 108 120 125 127 128 128 128STAIR_71 21 44 56 61 63 64 64 64 64STAIR_61 13 24 29 31 32 32 32 32 32STAIR_51 8 13 15 16 16 16 16 16 16STAIR_41 5 7 8 8 8 8 8 8 8STAIR_31 3 4 4 4 4 4 4 4 4STAIR_21 2 2 2 2 2 2 2 2 2STAIR_11 1 1 1 1 1 1 1 1 1Calculate the ration!

The rationisas follow:

STAIR\STEP1 2 3 4 5 6 7 8 9 10STAIR_101.0 1.6182 1.8389 1.9279 1.9661 1.9839 1.9921 1.9961 1.9961 2.0STAIR_91.0 1.6176 1.8395 1.9259 1.9667 1.984 1.9921 1.9922 2.0 2.0STAIR_81.0 1.619 1.8409 1.9286 1.9672 1.9841 1.9844 2.0 2.0 2.0STAIR_71.0 1.6154 1.8333 1.931 1.9677 1.9688 2.0 2.0 2.0 2.0STAIR_61.0 1.625 1.8462 1.9333 1.9375 2.0 2.0 2.0 2.0 2.0STAIR_51.0 1.6 1.8571 1.875 2.0 2.0 2.0 2.0 2.0 2.0STAIR_41.0 1.6667 1.75 2.0 2.0 2.0 2.0 2.0 2.0 2.0STAIR_31.0 1.5 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0STAIR_21.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0STAIR_11 1 1 1 1 1 1 1 1 1

运行结果

当N取值为10时候的输出如上,第一个数组为初始数组,全为0;第二个是计算出的所有L(N,M),每一行表示限定台阶数的情况下,不同最大步数对应的走法数。其中可以看出,STEP=2时候,第二列为斐波那契数列。值得注意的是,当有N个台阶且每一步最多跨N个台阶时候,有L(N,N) = 2^(N-1)。这是一个很有意思的发现,主程序代码(见函数result的注释)中对这个进行了一个形式化的证明。

同时,代码还对N=10的情况,计算了每一列相邻的数据的比例。可以看出,STEP=2时候,很熟悉的斐波那契数列的黄金分割比例1.6182。

进一步扩展

这个问题和另一个经典的“正整数分割问题”有些类似,想请自行Google之。值得注意的是,正整数分割中,如果考虑分割的顺序,即(1+2+1),(1+1+2),(2+1+1)是整数4的不同分割的话,此时的情况与N个台阶,每次最多跨N个台阶的走法数问题完全一致。其总数为

L(N,N) = 2^(N-1)

45>

python上台阶问题_“上台阶问题”的分析相关推荐

  1. python和苹果_苹果手机评论情感分析(附python源码和评论数据)

    原标题:苹果手机评论情感分析(附python源码和评论数据) 首先抓取网页上的数据,每一页十条评论,生成为一个txt文件. 数据链接 回复公众号 datadw 关键字"苹果"获取. ...

  2. python基因差异分析_差异表达基因的分析(2)

    应学生及个别博友的要求,尽管专业博文点击率和反应均很差,但在去San Diego参加PAG会议之前,还是抽时间给出[R高级教程]的第二专题.专题一给出了聚类分析的示例,本专题主要谈在表达谱芯片分析中如 ...

  3. python jieba 文本相似度_文本相似度分析(基于jieba和gensim)

    ##基础概念 本文在进行文本相似度分析过程分为以下几个部分进行, 文本分词 语料库制作 算法训练 结果预测 分析过程主要用两个包来实现jieba,gensim jieba:主要实现分词过程 gensi ...

  4. 用python分析小说_用Python对哈利波特系列小说进行情感分析

    原标题:用Python对哈利波特系列小说进行情感分析 准备数据 现有的数据是一部小说放在一个txt里,我们想按照章节(列表中第一个就是章节1的内容,列表中第二个是章节2的内容)进行分析,这就需要用到正 ...

  5. python是面向对象还是面向过程的语言_关于python是面向对象还是面向过程的分析...

    关于python是面向对象还是面向过程的分析 发布时间:2020-04-07 16:10:55 来源:亿速云 阅读:24 作者:小新 今天小编给大家分享的是关于python是面向对象还是面向过程的分析 ...

  6. 【毕业设计_课程设计】基于Python的南京二手房数据采集及可视化分析

    文章目录 0 项目说明 1 内容简介 2 应用技术介绍 3 数据采集 3.1 数据清洗 4 数据可视化 5 项目工程 0 项目说明 基于Python的南京二手房数据采集及可视化分析 提示:适合用于课程 ...

  7. python方差齐性检验_方差分析中的方差齐性检验_方差齐性检验结果分析

    方差分析中的方差齐性检验_方差齐性检验结果分析_方差分析 齐性检验 方差分析时的方差齐性检验是方差分析的前提条件,还是只是后面进行均值的多重比较时选择分析方法的依据?看过几本书,这两种观点都有.我看方 ...

  8. python空气质量分析与预测_干货!如何用 Python+KNN 算法实现城市空气质量分析与预测?...

    原标题:干货!如何用 Python+KNN 算法实现城市空气质量分析与预测? 作者 | 李秋键 责编 | 伍杏玲 封图 | CSDN 付费下载自东方 IC 出品 | CSDN(ID:CSDNnews) ...

  9. python日本 老龄化分析_基于Python关于世界自杀率影响因素的分析以及机器学习预测...

    基于Python关于世界自杀率影响因素的分析以及机器学习 预测 文/刘子桦 马若炎 [摘 要]摘 要 [期刊名称]<电子技术与软件工程> [年(卷),期]2019(000)017 [总页数 ...

  10. python开发程序知道微信好友是否已读信息吗_微商成功神器,python程序员教你,一键分析微信好友近期所有信息...

    好友太多怎么保活 相信做微商的微信好友都会很多,多到很多都成了"僵尸"好友,但是想要成为一个成功的微商,要有两点: 1.好友多,基数决定高度 2."活的"好友多 ...

最新文章

  1. GitHub有趣分享:Thanos(灭霸命令)
  2. 【每日训练】2020/11/9(Splay ?rope大法好!、数论、构造补图)
  3. 使用OpenSSH远程管理Linux服务器
  4. Apache Flink和Kafka入门
  5. webstorm 代码提示
  6. 易语言操作php文本文件,易语言对文本操作的步骤教学
  7. python cannot import name main_virtualenv: cannot import name 'main'
  8. 虚拟机网络适配器的三种模式详解及其配置
  9. 必知必会--HashMap容量细节
  10. DEFCON 23即将展开物联网“大屠杀”
  11. Python测试三角函数的正交性
  12. 牛逼哄哄的富士康老板郭台铭低头了,夏普将向三星供应液晶面板
  13. python 高斯白噪声-python高斯白噪声
  14. 红米note4高配版 电量用完,充不进去电,解决办法
  15. linux zip命令打包压缩文件目录
  16. Linux内存管理二(页表)
  17. SfxMCP基于rtsp协议H5无插件直播方案中RTSP设备的接入方法 - sfxlab
  18. Macbook Pro睡眠后频繁唤醒
  19. 拿去打包上线!一套代码实现1对1 、1对N在线课堂与低延迟大班课
  20. python中info的用法_使用Python中的data.info()显示所有信息

热门文章

  1. 【ubuntu】The following signatures couldn‘t be verified because the public key is not available
  2. 设置iPhone来电铃声(图文教程)
  3. 原则与思维模型--《思维模型》2
  4. 什么查重软件比较好用?
  5. 浅谈中国现货市场环境对期货市场发展的影响
  6. python cli_测试Python命令行(CLI)应用程序的4种技术
  7. Spring Kafka 之 @KafkaListener 单条或批量处理消息
  8. C#获取屏幕的分辨率
  9. 框架内(React)网页打印的实现
  10. 戴尔微型计算机7050配置,小巧彪悍 戴尔 OptiPlex 7050 微型机评测