DeepRest

Domino and Tromino Tiling

Dec 10th, 2021 (edited)
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.84 KB | None | 0 0
  1. #Intuitive Aprroach: O(n2) time and O(n) space
  2. #--------------------Logic--------------------
  3. """
  4. For every value of n, there are certain ATOMIC (indivisible) tiling patterns that cannot be build from tilings of smaller boards(smaller values of n), thus cannot be obtained recursvely. For example:
  5. (USE DESKTOP MODE)
  6. For n=1                 For n=2               For n=3                 For n=4                     For n=5
  7. x                       x x                   x y y      x x y        x y y z      x x y y        x y y z z      x x y y z
  8. x                       y y                   x x y      x y y        x x z z      x z z y        x x a a z      x a a z z
  9. Vertical                2 Horizontal          Two Trominoes and n-3 Dominoes combo (for n>2) .............................
  10. Domino                  Dominoes
  11. (For these arrangements except for the first and last column no other column has same characters [grids in same column belong to different tiles]; thus pattern is indivisible)
  12. Thus for all n > 2 there exists two such atomic arrangements (this accounts for 2 in the dp equation, explained below)
  13.  
  14. Thus in order to build the i-tiling we can add these atomic patterns of sizes 1 to i to the right of all possible tilings,dp[j] ; j in [i-1, 0].
  15. let dp[i] = no. of ways to tile 2*i board completely
  16. So: dp[i] =
  17. dp[i-1]*no. of atomic pattern of size 1 (=1) +
  18. dp[i-2]*no. of atomic pattern of size 2 (=1) +
  19. dp[i-3]*no. of atomic pattern of size 3 (=2) +
  20. dp[i-4]*no. of atomic pattern of size 4 (=2) + .... +
  21. dp[0]*no. of atomic patterns of size i                 {dp[0] = 1 (one way: no tiling)}
  22. We consider adding atomic patterns, inorder to avoid problem of overcounting
  23.  
  24. Thus: dp equation is dp[i] = dp[i-1] + dp[i-2] + 2*(dp[i-3]+dp[i-4]+...+dp[1]+dp[0]) for all n
  25. """
  26. class Solution(object):
  27.     def numTilings(self, n):
  28.         """
  29.        :type n: int
  30.        :rtype: int
  31.        """
  32.         dp = [1, 1] + [2]*(n-2) #Prepopulating with atomic patterns of sizes 1 to n (1, 1, 2, 2, 2,.....2)
  33.         for i in range(n):
  34.             for j in range(1, i+1):
  35.                 dp[i] += dp[i-j] + dp[i-j]*(j>2)
  36.         return dp[-1] % int(1e9+7)
  37.  
  38. #Refined approach O(n) time and constant auxillary space
  39. """
  40. Using prefix(/partial) sum like logic
  41. dp[i] = dp[i-1] + dp[i-2] + 2*(dp[i-3]+ ... +dp[0])
  42.      = dp[i-1] + dp[i-3]  + (dp[i-2] + dp[i-3] + 2*(dp[i-4] +...+ dp[0])    ...distributing the 2*dp[i-3] term
  43.      = dp[i-1] + dp[i-3] + dp[i-1]
  44.      = 2*dp[i-1] + dp[i-3]
  45. """
  46. '''
  47. class Solution(object):
  48.    def numTilings(self, n):
  49.        """
  50.        :type n: int
  51.        :rtype: int
  52.        """
  53. #a is dp[i]; b is dp[i-1]; c is dp[i-2]:  they become dp[i-1], dp[i-2], dp[i-3] in next iteration and so on...
  54.        a, b, c = 1, 1, 0
  55.        for i in range(n-1):
  56.            a, b, c = (2*a + c)%int(1e9+7), a, b
  57.        return a
  58. '''
Add Comment
Please, Sign In to add comment