我有一个像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
你可以重复数字,只要他们没有超过你的金额。哪种方式最适合编程?
答案 0 :(得分:8)
这是对变更问题的略微修改。您应该能够找到关于此问题的大量论文,动态编程解决方案不会超过20行代码。
答案 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);
}