计算之字形序列

时间:2012-10-08 16:21:45

标签: python dynamic-programming combinatorics

Zigzag序列是一个序列,其中每个元素都少于或多于它的邻居:1 3 22 1 2是Z字形,1 2 31 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:])

2 个答案:

答案 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)

然后长度为nn>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))