当我们为N个数字中的每一个给出一组N个数字和范围时,枚举所有可能的序列

时间:2016-06-13 00:08:23

标签: algorithm enumeration combinatorics

问题陈述:

我们得到了

  1. 一组T号S1,S2,...... ST

  2. 一个名为Range

  3. 的整数

    这意味着S1可以采用(2 * Range + 1)值(S1-Range,S1-Range + 1,... S1,S1 + 1,...... S1 + Range) 类似地,S2,... ST可以采用2 * Range + 1值

    问题1:如何枚举所有可能的序列?即所有(2 * Range-1)^ T序列(S1-Range,S2,... ST),S1-Range + 1,S2,... ST),.....,(S1,S2) -Range,S3,...... ST)等

    问题2:我如何仅列出总和为S1 + S2 + ... + ST?

    的序列

    问题1:我正在考虑的方法是做一个

    for (i=0; i<pow(Range,T);i++)
    {
       Sequences that can be derived from i are
       1. {Si + i mod pow(Range,i)}
       2. {Si - i mod pow(Range,i)}
    }
    

    还有其他更优雅的解决方案吗?

    此外,对问题2的任何想法?

1 个答案:

答案 0 :(得分:2)

对于#1,一种方法是将其视为增加数字的方式。你递增最后一个数字,当它溢出时你将它设置回初始值(0)并递增下一个数字。

因此,创建一个大小为T的数组,然后将元素初始化为(S1-Range,S2-Range,...,ST-Range)。打印出来。

现在将最后一个值增加到ST-Range + 1。打印出来。继续递增和打印,直到达到ST +范围。尝试增加时,重置回ST-Range,然后向左移动一个位置并递增。如果溢出也重复。如果一直向前移动,你就完成了,否则打印出来。

// Input: T, S[T], Range
create V[T]
for (i in 1..T):
    V[i] = S[i] - Range
loop forever {
    print V
    i = T
    V[i]++
    while V[i] > S[i] + Range {
        V[i] = S[i] - Range
        i--
        if i < 1:
            return // we're done
        V[i]++
    }
}

对于#2,它有点不同。对于描述,我将忽略S的值,并为每个位置忽略delta(-Range,...,0,...,+ Range)的焦点,称之为D.

由于sum(D)= 0,初始值集为(-Range,-Range,...,+ Range,+ Range)。如果T是偶数,则前半部分是-Range,后半部分是+ Range。如果T为奇数,则中间值为0.

现在看看你希望如何进行迭代:

-2 -2  0  2  2
-2 -2  1  1  2
-2 -2  1  2  1
-2 -2  2  0  2  (A)
-2 -2  2  1  1
-2 -2  2  2  0
-2 -1 -1  2  2
-2 -1  0  1  2
-2 -1  0  2  1
-2 -1  1  0  2

这里的逻辑是你跳过最后一位数,因为它总是其他数字的函数。您可以递增可以递增的最右侧数字,并将其右侧的数字重置为可能得到总和(D)= 0的较低值。

逻辑有点复杂,所以我会让你有趣的写作。 ; - )

一个好的帮助方法,如果给定一个起始增量,将是一个将某个位置后的数字重置为最低可能值的方法。然后,您可以通过调用reset(1, 0)来使用它来初始化数组,即使用起始增量0重置位置1..T。

然后,当您在上面标记为A的步骤中将D [3]增加到2时,您调用reset(4, -2),即使用-2的起始delta重置位置4..5。最后一位的最大值为2(范围),则表示D [4]不能低于0.