'Number of ways to sit in a 2XN grid
I had this question in an interview but I was not able to solve it.
We have a grid of 2 rows and n columns. We have to find the number of ways to sit M men and W women given no men can sit adjacent or in front of each other.
I thought of solving it by Dynamic Programming but I'm not sure how to get the recurrence relation.
I know that if I am at (0,i), I can go to (1,i+1) but I don't know how to keep track of counts of men and women so far. Can anybody help me with the recurrence relation or states of dp?
Solution 1:[1]
Recurrence relation
Here is one recurrence relation I could thing of.
Let's call n_ways(N, W, M, k)
the number of ways to seat:
W
women- and
M
men - in the remaining
N
columns - knowing there was
k
men in the previous column.k
can only take values 0 and 1.
n_ways(N, 0, 0, k) = 1
n_ways(N, W, M, k) = 0 if M > N or W+M > 2*N
n_ways(N, W, 0, k) = ((2*N) choose W)
n_ways(N, 0, M, 0) = 2 * (N choose M)
n_ways(N, 0, M, 1) = (N choose M)
n_ways(N, W, M, 0)
= n_ways(N-1, W, M, 0) // put nobody in first column
+ 2 * n_ways(N-1, W-1, M, 0) // put 1 woman in first column
+ n_ways(N-1, W-2, M, 0) // put 2 women in first column
+ 2 * n_ways(N-1, W-1, M-1, 1) // put 1 woman & 1 man in first column
+ 2 * n_ways(N-1, W, M-1, 1) // put 1 man in first column
n_ways(N, W, M, 1)
= n_ways(N-1, W, M, 0) // put nobody in first column
+ 2 * n_ways(N-1, W-1, M, 0) // put 1 woman in first column
+ n_ways(N-1, W-2, M, 0) // put 2 women in first column
+ n_ways(N-1, W-1, M-1, 1) // put 1 woman & 1 man in first column
+ n_ways(N-1, W, M-1, 1) // put 1 man in first column
Testing with python
Since I'm too lazy to implement dynamic programming myself, I instead opted for caching using python's functools.cache
.
I implemented the recurrence relation above as a cached recursive function, and got the following results:
Number of ways to seat w women and m men in n columns:
n, w, m --> ways
0, 0, 0 --> 1
0, 0, 1 --> 0
0, 1, 0 --> 0
1, 2, 0 --> 1
1, 0, 2 --> 0
1, 1, 1 --> 2
2, 2, 2 --> 2
3, 3, 3 --> 2
4, 6, 2 --> 18
10, 15, 5 --> 2364
10, 10, 10 --> 2
Here is the python code:
from functools import cache
from math import comb
@cache
def n_ways(n, w, m, k):
if w == m == 0:
return 1
elif m > n or w + m > 2 * n:
return 0
elif m == 0:
return comb(2*n, w)
elif w == 0:
return (2-k) * comb(n, m)
else:
r_0, r_w, r_ww, r_wm, r_m = (
n_ways(n-1, w, m, 0),
n_ways(n-1, w-1, m, 0),
n_ways(n-1, w-2, m, 0) if w > 1 else 0,
n_ways(n-1, w-1, m-1, 1),
n_ways(n-1, w, m-1, 1)
)
return (r_0 + r_w + r_w + r_ww + r_wm + r_m) + (1-k) * (r_wm + r_m)
if __name__=='__main__':
print(f'Number of ways to seat w women and m men in n columns:')
print(f' n, w, m --> ways')
for w, m in [(0, 0), (0, 1), (1, 0), (2, 0), (0, 2),
(1, 1), (2, 2), (3, 3), (6, 2), (15, 5),
(10, 10)]:
n = (w + m) // 2
print(f'{n:2d}, {w:2d}, {m:2d} --> ', end='')
print(n_ways(n, w, m, 0))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |