4

I am trying to solve a dynamic programming problem and part of the problem involves finding number of permutations of a set of 'p' numbers that will sum up to a number 'n'. Each number in the set of p numbers should be between 0 to n inclusive.

For example if n = 4 and p = 3, I have the following 12 permutations

{4,0,0},{0,4,0},{0,0,4}
{2,2,0},{2,0,2},{0,2,2}
{1,3,0},{1,0,3},{0,1,3}
{1,1,2},{1,2,1},{2,1,1}

I started with this DP approach.

n(i,j) represents number of ways of representing n using i,j in p positions 

My base case would be

n(i,0) = n(0,i) = p   

(for example, n(4,0) in p=3 places is 3 which is {4,0,0},{0,4,0},0,0,4}

recursive case

n(i,j) = n(i,j-1)*n(i-1,j)

(example : n(1,2) = n(1,1) * n(0,2) which recurses to n(1,0) * n(0,1) * 2)

I am not sure if I am proceeding in the right direction as the above approach doesn't lead me to a correct answer. Please guide me in the right direction.

quirkystack
  • 1,387
  • 2
  • 17
  • 42
  • Could this be a homework problem? –  Jun 28 '13 at 23:32
  • 1
    The permutations part seems almost completely separate--addition is commutative and associative. Looks like you can use DP to solve the simpler problem: Find the number of sets of `p` numbers that sum to `n` where each member of a set has range `[0,n]`. Then once you have those sets you can just compute permutations pretty easily (just remember to remove duplicate permutations! For example `011` only has `3!/2!` permutations if the two `1`s are indistinguishable.) – rliu Jun 28 '13 at 23:49
  • 1
    @MikeW it's not homework.. was trying out [this](https://www.hackerrank.com/challenges/count-scorecards) problem – quirkystack Jun 28 '13 at 23:59
  • @quirkystack Ah. That's not quite the same problem. In this case, you can't have one person win all the games. Consider if you have three players and only player two wins games. Then what happened in player one vs. player three? – rliu Jun 29 '13 at 01:40
  • actually I would have the maximum score possible for the rest of the blanks. So , in the above example, I would take max value for the three players to be 2 and not 3 – quirkystack Jun 29 '13 at 03:45
  • @quirkystack Ah but that still doesn't work because `(0, 2, 0)` is not a solution to the problem you posted in the comments. In particular, there's three players so there are three games played. That means that the sum over the set must be 3. If you set `n = 3` then you're out of luck. If you set `n = 2` then you're still out lof luck (because you'd output `(0, 2, 0)` as a solution when it's not). I think I have the DP solution, let me think about it and write up as an edit to my existing answer. I may submit some code too to that site to verify. – rliu Jun 29 '13 at 03:57
  • @quirkystack Been working on it on and off the past couple of days... not much progress, heh. The only conclusions I've established is that the number grows insanely fast. If you remove permutations it's still exponential. Since `N <= 40` it's not even feasible to generate all of the sets up to isomorphism (i.e. without considering permutations). So the DP solution has to do something that doesn't involve generating all of the sets (I'm assuming there's a reasonable time limit at hackerrank...). – rliu Jul 01 '13 at 19:52
  • yes it will give out a Time Limit Exceeded message even if the answer is right – quirkystack Jul 01 '13 at 21:23

1 Answers1

7

Contrary to my comment, this problem is actually easier to solve if we count the number of sets and the permutations of those sets at the same time.

If we only need to count instead of actually generating each of the sets, we can do so directly with some simple combinatorics. Let's fix p = 3, n = 5 for our example and imagine that we have n = 5 balls:

o o o o o

Now the question is equivalent to, how many ways can we split the balls into groups of 3 where each group can have [0, 5] balls? Imagine if we had p - 1 = 2 sticks that we could individually place anywhere: before all five balls, after all five balls, and between any two balls. For example:

| o o | o o o => (0, 2, 3)
o | | o o o o => (1, 0, 4)
o o o o | | o => (4, 0, 1)

Notice how the questions are equivalent? Anyway we can put those sticks, we can also partition our n balls into p sets. Notice that we only need p - 1 sticks to generate the p numbers (all the balls before the first stick are the first group, all the balls after the last stick are the last group, any balls between two sticks are the other groups).

So now our question is how many ways can I arrange my n balls and p - 1 sticks? You can think of it as having n + (p - 1) slots and you are just picking the n spots for the balls... and the rest are where the sticks go. Thinking of it this way we can apply a basic formula of combinatorics (it's proven using the axiomatic rule of sum and rule of product... not sure I've ever even seen the proof):

(n + (p - 1)) Choose n = (n + (p - 1))! / n! / (p - 1)!

So in our example, it's 7! / 5! / 2! = 21. And you can see that in your example it would be 6! / 4! / 2! = 15. You missed a few permutations (for example, {0, 3, 1}).

You can also solve this with DP by a simple recursive equation. Basically

`f(n, p) = Sum over i = 0 to n, f(n - i, p - 1)`

and memoize some of the values of f. The idea is, you pick the value for the first member of your set S and then the next recursive call picks the next member of S and so on. The base cases would probably be something like f(0, p) = 1 and f(n, 0) = 0 and otherwise you can use the recursive case. The closed form is obviously a lot more performant though if you don't actually need the sets themselves.

rliu
  • 1,148
  • 6
  • 8