Zigzag序列是一个序列,其中每个元素都少于或多于它的邻居:1 3 2
和2 1 2
是Z字形,1 2 3
和1 2 2
不是。
给两个数字给出n,k找出从数字1 ...中可以生成多少个大小为n的序列
示例:n = 3 k = 3答案:10
121,212,131,313,232,323,132,231,312,213(为了清晰起见,无需生成)
我来到这个解决方案。请告诉我是否可以做得更好。
import sys
ZAG = {}
ZIG = {}
def zag(n, i):
result = 0
for j in xrange(1, i):
if (n - 1, j) not in ZIG:
ZIG[(n - 1, j)] = zig(n - 1, j)
result += ZIG[(n - 1, j)]
return result
def zig(n, i):
result = 0
for j in xrange(i + 1, MAX_NUMBER + 1):
if (n - 1, j) not in ZAG:
ZAG[(n - 1, j)] = zag(n - 1, j)
result += ZAG[(n - 1, j)]
return result
def count(n):
if n == 1:
return MAX_NUMBER
result = 0
for i in xrange(1, MAX_NUMBER + 1):
ZIG[(1, i)] = 1
ZAG[(1, i)] = 1
for i in xrange(1, MAX_NUMBER + 1):
result += 2*zag(n, i)
return result
def main(argv):
global MAX_NUMBER
MAX_NUMBER = int(argv[1])
print count(int(argv[0]))
if __name__ == "__main__":
main(sys.argv[1:])
答案 0 :(得分:0)
如果通过递归调用Zig(小于最后一个数字的值)和Zag(大于最后一个数字的值)生成序列,迭代可能性,它会变得更好,你可以使它更好(计算通过将已解决的子问题存储在静态表中,而不是在内存方面。
答案 1 :(得分:0)
整个序列中的订单以前两个元素的顺序给出。有两种类型的排序:up-down-up -...和down-up-down -...两个排序的序列数相同,因为一个排序的序列可以通过交换每个顺序以其他顺序转换使用x
编号k+1-x
。
让U_k(n)
为序列数,首先是长度为n
的顺序。设U_k(n, f)
为序列数,首先是长度n
,第一个是f
。类似定义D_k(n)
和D_k(n, f)
。
然后长度为n
(n>1
)的序列数为:
U_k(n) + D_k(n) = 2*U_k(n) = 2*( sum U_k(n, f) for f in 1 ... k ).
相同的论点给出:
U_k(n, f) = sum D_k(n-1, s) for s = f+1 ... k
= sum U_k(n-1, s) for s = 1 ... k-f
U_k(1, f) = 1
修改强>
实施稍微简单一些。 M(n,k)
返回第n行(从后面开始),C(n,k)
计算序列数。
def M(n, k):
if n == 1: return [1]*k
m = M(n-1, k)
return [sum(m[:i]) for i in xrange(k)][::-1]
def C(n, k):
if n < 1: return 0
if n == 1: return k
return 2*sum(M(n,k))