如何生成整数分区?

时间:2009-09-29 00:30:52

标签: algorithm combinations

我有一个像1,2,3这样的数字列表,我想找到总结到特定数字的所有组合模式,例如:5。例如:

Sum=5
Numbers:1,2,3
Patterns:

1 1 1 1 1
1 1 1 2
1 1 3
1 2 2
2 3

你可以重复数字,只要他们没有超过你的金额。哪种方式最适合编程?

7 个答案:

答案 0 :(得分:8)

这是对变更问题的略微修改。您应该能够找到关于此问题的大量论文,动态编程解决方案不会超过20行代码。

http://en.wikipedia.org/wiki/Change-making_problem

答案 1 :(得分:2)

答案 2 :(得分:2)

这些被称为the partitions of a number,你的问题似乎强加了你可以在分区中使用哪些数字的约束。

答案 3 :(得分:2)

这个问题被称为“双重限制整数分区”。如果“允许”总和为5的数字来自集合V,那么它被称为“乘法受限整数分区”。 Riha和James有一篇论文:“算法29:双倍和多重限制分区的高效算法”计算Vol 16,No 1-2,pp 163-168(1976)。您应该阅读该论文并实施他们的算法。了解如何执行此操作将允许您实现特定问题的唯一优化。

答案 4 :(得分:0)

我会以递增的方式首先从最高的数字开始。然后,每次从最高级别开始,并进入与数字一样多的级别。累积级别超过您的值后,请下拉到下一个数字。如果仍然太大(或很小),立即返回一个级别并将该级别减少到下一个数字,然后再次从顶部开始到下一个更深级别..

答案 5 :(得分:0)

    public static List<List<string>> Partition(int n, int max, string prefix)
    {

        if (n == 0)
        {
            _results.Add(prefix.Split(new char[] { ',' }).ToList());
        }

        for (int i = Math.Min(max, n); i >= 1; i--)
        {
            Partition(n - i, i, prefix + "," + i);
        }

        return _results;
    }

答案 6 :(得分:-1)

您可以使用以下代码..它会根据您的需要为您提供准确答案。

void print(int n, int * a)

{
   int i ; 

   for (i = 0; i <= n; i++) 

   {

  printf("%d", a[i]); 

  }

 printf("\n"); 

}


void integerPartition(int n, int * a, int level)

{

   int first; 

  int i; 

  if (n < 1) 

 return ;    

 a[level] = n;

  print(level, a);

  first = (level == 0) ? 1 : a[level-1];

  for(i = first; i <= n / 2; i++)

   {

       a[level] = i; 

       integerPartition(n - i, a, level + 1);

   }

}

int main()

  {

   int n = 10;     

   int * a = (int * ) malloc(sizeof(int) * n); 

   integerPartition (n, a, 0); 

   return(0);

}