问题
I have a list of numbers like 1,2,3 and I want to find all the combination patterns that sum up to a particular number like 5. For example:
Sum=5
Numbers:1,2,3
Patterns:
1 1 1 1 1
1 1 1 2
1 1 3
1 2 2
2 3
You're allowed to repeat numbers as far as they don't go over your sum. Which way would be best to program this?
回答1:
This is a slight modification of the change making problem. You should be able to find plenty of papers on this problem, and a dynamic programming solution would take no more than 20 lines of code.
http://en.wikipedia.org/wiki/Change-making_problem
回答2:
This might also help: Dynamic Programming: Combination Sum Problem
回答3:
These are called the partitions of a number , and your problem seems to impose the constraint of which numbers you're allowed to use in the partition.
回答4:
This problem is known as a "doubly restricted integer partition." If the numbers "allowed" to sum to 5 were from a set V, then it is known as "multiply restricted integer partition." There is a paper by Riha and James: "Algorithm 29: Efficient algorithms for doubly and multiply restricted partitions" Computing Vol 16, No 1-2, pp 163-168 (1976). You should read that paper and implement their algorithm. Understanding how to do it will allow you to implement optimizations unique to your specific problem.
回答5:
I would do it recursively starting with the highest numbers first. then, each time in start with the highest level and go in as many levels as numbers. As soon as the cumulative level exceeds your value, drop down to the next number. If still too large (or small), immediately return back one level and decrease THAT to the next number down, then to the next deeper level starting at the top again..
回答6:
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;
}
回答7:
You can use following code .. it wiil give you a exact answer as you want..
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);
}
来源:https://stackoverflow.com/questions/1490001/how-do-i-generate-integer-partitions