题目
已知从山脚到山顶共有m个台阶,一次可爬a-b个台阶,由于年久失修,部分台阶已坏无法站立,已知坏的台阶共有n个并给出所在位置,问共有多少种登山方案(如果无法登山山顶返回0,结果大于则对其取模)?
输入描述
台阶总数m,一次最少可爬台阶数a,一次最大可爬台阶数b,坏掉的台阶n,之后n行为坏掉台阶的编号,编号从1开始。
输出描述
一个数字,代表登山方案的个数
解题思路
思路一:暴力法
枚举所有的登山方案,得到可行的登山方案个数。
思路二:动态规划
为了方便说明,将原问题转化为3个难度递增的小问题进行逐一解决。
- m级台阶,一次最多可爬1-b个,有多少种登山方案?
- m级台阶,一次最多可爬a-b个,有多少种登山方案?
- m级台阶,n级损坏,一次最多可爬a-b个,有多少种登山方案?
问题1
令f(m,b)表示登山方案的个数,第一步可以跨1-b个台阶,若登上1个台阶,则余下的方案个数为f(m-1,b);若登上k个台阶,则余下的方案个数为f(m-k,b)个,因此可以得到f(m,b)=f(m-1,b)+f(m-2,b)+...+f(m-b,b),其中m<=0时,f(m,b)=0,m=1时,f(m,b)=1,m=b时,f(m,b)=f(m,b-1)+1。
input_m = 100
input_b = 2
solution_table = {}
def get_solutions(m, b):
if m <= 0 or b <= 0:
return 0
elif m == 1:
return 1
elif m == b:
if (m, b) in solution_table:
solution = solution_table[(m, b)]
else:
solution = get_solutions(m, b - 1) + 1
solution_table[(m, b)] = solution
return solution
else:
if (m, b) in solution_table:
solution = solution_table[(m, b)]
else:
solution = sum(get_solutions(m - i - 1, b) for i in range(b))
solution_table[(m, b)] = solution
return solution
result = get_solutions(input_m, input_b)
result = result % 1000000007
print(result)
问题2
令f(m,a,b)表示登山方案的个数,第一步可以跨a-b个台阶,若登上a个台阶,则余下的方案个数为f(m-a,a,b);若登上k个台阶,则余下的方案个数为f(m-k,a,b)个,因此可以得到f(m,a,b)=f(m-a,a,b)+f(m-a-1,a,b)+...+f(m-b,a,b)。
input_m = 100
input_a = 2
input_b = 5
solution_table = {}
def get_solutions(m, a, b):
if m - a < 0:
return 0
elif m == a:
return 1
elif m >= a + b:
if (m, a, b) in solution_table:
solution = solution_table[(m, a, b)]
else:
solution = 0
for i in range(a, b + 1):
solution += get_solutions(m - i, a, b)
solution_table[(m, a, b)] = solution
else:
if (m, a, b) in solution_table:
solution = solution_table[(m, a, b)]
else:
solution = 0
for i in range(a, b + 1):
if m - i > 0:
solution += get_solutions(m - i, a, b)
elif m - i == 0:
solution += 1
else:
break
solution_table[(m, a, b)] = solution
return solution
result = get_solutions(input_m, input_a, input_b)
result = result % 1000000007
print(result)