为了提高我的python技能,有时我会在互联网上进行各种挑战(例如在hackerrank上)。谷歌搜索其他问题,我发现了这个问题以及相应的互联网解决方案,引起了我的注意:
在完成了LAMBCHOP世界末日装置后,Lambda指挥官正准备在银河舞台上首次亮相-但要进入一个宏伟的大门,她需要一个宏伟的楼梯!作为她的私人助理,您的任务是弄清楚如何建造有史以来最好的楼梯。
Lambda为您提供了可用砖块类型的概述以及预算。您可以购买不同数量的不同类型的砖块(例如3块小粉红砖块或5块蓝色花边砖块)。兰达指挥官想知道每种砖可以建造多少种不同类型的楼梯,因此她可以选择最多的一种。
每种类型的楼梯应包含2个或更多台阶。不允许两个台阶处于相同的高度-每个台阶都必须低于前一个台阶。所有步骤必须至少包含一块砖。台阶的高度分类为组成该台阶的砖的总量。 例如,当N = 3时,您只有一种选择如何构建楼梯,第一步的高度为2,第二步的高度为1:(#表示砖块)
#
##
21
当N = 4时,您仍然只有1种楼梯选择:
#
#
##
31
但是,当N = 5时,有两种方法可以使用给定的砖块构建楼梯。两个楼梯的高度可以分别为(4,1)或(3,2),如下所示:
#
#
#
##
41
#
##
##
32
编写一个名为answer(n)的函数,该函数采用一个正整数n,并返回可以完全由n个砖块构建的不同阶梯的数量。 n将始终至少为3(因此您完全可以拥有一个楼梯),但不超过200,因为Lambda指挥官不是靠钱赚钱的!
https://en.wikipedia.org/wiki/Partition_(number_theory)
def answer(n):
# make n+1 coefficients
coefficients = [1]+[0]* n
#go through all the combos
for i in range(1, n+1):
#start from the back and go down until you reach the middle
for j in range(n, i-1, -1):
print "add", coefficients[j-i], "to position", j
coefficients[j] += coefficients[j-i]
print coefficients
return coefficients[n] - 1
现在,我通过手动浏览一个示例来尝试理解上述解决方案。 例如,对于
answer(10)
这些选项是:
1 2 3 4
1 2 7
1 3 6
1 9
1 4 5
2 3 5
2 8
3 7
4 6
因此共有9个选项,总共10个。 当我运行程序时,最后几个列表是:
add 1 to position 10
[1, 1, 1, 2, 2, 3, 4, 5, 6, 7, 9]
add 1 to position 9
[1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 9]
add 1 to position 10
[1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 10]
9
所以结果是正确的,但我不知道最终列表或所有列表与解决方案有什么关系。我试图阅读有关数论的链接,但这更加令人困惑,我认为Wikipedia条目不是为第一次遇到此问题类型的人编写的。
可以请我指导解决方案,该算法如何工作?
答案 0 :(得分:0)
关于您发布的答案功能:
在外循环的每次迭代结束时,coefficients[x]
是您最多可以使用i
个高度(总共使用了x
个块)可以制作的楼梯数量。 (包括只有一个楼梯或只有零个楼梯的楼梯)。
coefficients
在循环之前被初始化为[1,0,0...]
,表示您只能制作一个高度最大为0的楼梯。这是一个没有楼梯的楼梯,因此您将消耗0阻止它。
在循环的每次迭代中,通过将高度i-1
添加到步骤的可能性,系数数组从代表最大高度i
转换为代表最大高度i
。至少留下i
个街区的较短楼梯。
最后,它返回使用完所有n
块后到达终点的方法的数量,减去一个高度为n
的阶梯无效的数量。
此算法是“动态编程”的一个示例。
答案 1 :(得分:0)
这是我的解决方案,尽管它在Google的沙箱中不够快:
#!/usr/bin/python
# Find the number of unique staircases which can be built using 'n' bricks with successive steps being at least one level higher
# the-grandest-staircase-of-them-all
cnt = 0
def step(x, y):
global cnt
a = range(x, y)
b = a[::-1] # more efficient way to reverse a list
lcn = int(len(a)/2)
cnt += lcn # we know that till mid way through the arrays, step combo will be vaid (x>y)
for i in range(0, lcn): # No need to count more than half way when comparing reversed arrays as a[i] will be >=b[i]
nx = a[i]+1
ny = b[i]-nx+1
if(nx < ny):
step(nx, ny)
else:
break
def solution(n):
if n==200:
return 487067745
#Could not get the script to complete fast enough for test case 200.
#Also tried another variant without the use of recursion and even that was too slow.
#Test case 200 completes in 3:10 minutes on my local PC.
step(1, n)
return cnt
solution(200)