2013-11-20 48 views
6

我试图按照字典顺序(例如,编号)生成编号为K的给定整数N的像样分区。对于N = 5, K = 3我们得到:按其编号生成整数分区

5 = 1 + 1 + 1 + 1 + 1 
5 = 1 + 1 + 1 + 2 
5 = 1 + 1 + 3 
5 = 1 + 2 + 2 
5 = 1 + 4 
5 = 2 + 3 
5 = 5 

,第三个是1 + 1 + 3。 如何在不生成每个分区(使用C语言,但最重要的是我需要算法)的情况下生成此分区?

会发现在分区最大数量(假设我们可以发现分区d[i][j],数其中i是数量和j是它的分区的最大整数),则减少原来的号码和电话号码,我们所期待的。所以是的,我试图使用动态编程。仍在研究代码。

这并不在所有的工作:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 


FILE *F1, *F2; 


main() 
{ 
    long long i, j, p, n, k, l, m[102][102]; 
    short c[102]; 
    F1 = fopen("num2part.in", "r"); 
    F2 = fopen ("num2part.out", "w"); 
    n = 0; 
    fscanf (F1, "%lld %lld", &n, &k); 
    p = 0; 
    m[0][0] = 1; 
    for (i = 0; i <= n; i++) 
    { 
     for (j = 1; j <= i; j++) 
     { 
      m[i][j] = m[i - j][j] + m[i][j - 1]; 
     } 
     for (j = i + 1; j <= n; j++) 
     { 
      m[i][j] = m[i][i]; 
     } 
    } 
    l = n; 
    p = n; 
    j = n; 
    while (k > 0) 
    { 
     while (k < m[l][j]) 
     { 
      if (j == 0) 
      { 
       while (l > 0) 
       { 
        c[p] = 1; 
        p--; 
        l--; 
       } 
      break; 
     } 
     j--; 
    } 
    k -=m[l][j]; 
    c[p] = j + 1; 
    p--; 
    l -= c[p + 1]; 
    } 
//printing answer here, answer is contained in array from c[p] to c[n] 
} 
+0

使用动态编程来发现的(N,K)-partitions数目对于n zch

+0

试图在分区中查找最大数目(假设我们可以找到分区数量'd [i] [j]',其中'i'是数字,'j'是其分区中的最大整数),然后减少原始数量并我们正在寻找的数量,仍然在努力。 – siziyman

回答

3

下面是一些产生分区例如Python代码:

cache = {} 
def p3(n,val=1): 
    """Returns number of ascending partitions of n if all values are >= val""" 
    if n==0: 
     return 1 # No choice in partitioning 
    key = n,val 
    if key in cache: 
     return cache[key] 
    # Choose next value x 
    r = sum(p3(n-x,x) for x in xrange(val,n+1)) 
    cache[key]=r 
    return r 

def ascending_partition(n,k): 
    """Generate the k lexicographically ordered partition of n into integer parts""" 
    P = [] 
    val = 1 # All values must be greater than this 
    while n: 
     # Choose the next number 
     for x in xrange(val,n+1): 
      count = p3(n-x,x) 
      if k >= count: 
       # Keep trying to find the correct digit 
       k -= count 
      elif count: # Check that there are some valid positions with this digit 
       # This must be the correct digit for this location 
       P.append(x) 
       n -= x 
       val = x 
       break 
    return P 

n=5 
for k in range(p3(n)): 
    print k,ascending_partition(n,k) 

它打印:

0 [1, 1, 1, 1, 1] 
1 [1, 1, 1, 2] 
2 [1, 1, 3] 
3 [1, 2, 2] 
4 [1, 4] 
5 [2, 3] 
6 [5] 

这可能是用于生成任意分区而不生成所有中间分区。例如,有9253082936723602个分区300

print ascending_partition(300,10**15) 

打印

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 7, 8, 8, 11, 12, 13, 14, 14, 17, 17, 48, 52] 
+0

谢谢,我有生成所有分区的代码,但是应该有一个解决方案,用于按照此顺序生成一个带有正确数字的分区(生成所有作品太慢)。 – siziyman

+0

这里的代码一次生成一个分区。你可以简单地调用ascending_partition(n,k)和你想要的任何n和k的值。我只是放入循环进行测试。 –

+0

这仍然有必须通过所有分区工作的开销,对吧? (而不是简单地计算所需的) – Dukeling

0
def _yieldParts(num,lt): 
    ''' It generate a comination set''' 
    if not num: 
    yield() 
    for i in range(min(num,lt),0,-1): 
    for parts in _yieldParts(num-i,i): 
     yield (i,)+parts 


def patition(number,kSum,maxIntInTupple): 
    ''' It generates a comination set with sum of kSum is equal to number 
     maxIntInTupple is for maximum integer can be in tupple''' 
    for p in _yieldParts(number,maxIntInTupple): 
    if(len(p) <=kSum): 
     if(len(p)<kSum): 
     while len(p) < kSum: 
      p+=(0,) 
     print p 


patition(40,8,40) 

Output: 
------- 
(40,0,0,0,0,0,0,0) 
(39,1,0,0,0,0,0,0) 
. 
. 
. 
. 
+0

给你的代码解释。只有代码答案不值得赞赏。 –

+0

我已经给出了函数的注释。你可以得到一些想法。 – user3472760