Domino and Tromino tiling problem - GeeksforGeeks

05 Aug, 2021
Given a positive integer N, the task is to find the number of ways to fill the board of dimension 2*N with a tile of dimensions 2 × 1, 1 × 2, (also known as domino) and an ‘L‘ shaped tile(also know as tromino) show below that can be rotated by 90 degrees.
The L shape tile:

XX
X
After rotating L shape tile by 90:

XX
 X
or
X
XX
Examples:
Input: N = 3Output: 5Explanation:Below is the image to illustrate all the combinations:
Input: N = 1Output: 1
Approach: The given problem can be solved based on the following observations by:
Let’s define a 2 state, dynamic programming say dp[i, j] denoting one of the following arrangements in column index i.
The current column can be filled with 1, 2 × 1 dominos in state 0, if the previous column had state 0.
The current column can be filled with 2, 1 × 2 dominos horizontally in state 0, if the i – 2 column has state 0.
The current column can be filled with an ‘L‘ shaped domino in state 1 and state 2, if the previous column had state 0.
The current column can be filled with 1 × 2 shaped domino in state 1 if the previous column has state 2 or in state 2 if the previous column has state 1.
Therefore, the transition of the state can be defined as the following:dp[i][0] = (dp[i – 1][0] + dp[i – 2][0]+ dp[i – 2][1] + dp[i – 2][2]).dp[i][1] = dp[i – 1][0] + dp[i – 1][2].dp[i][2] = dp[i – 1][0] + dp[i – 1][1].
dp[i][0] = (dp[i – 1][0] + dp[i – 2][0]+ dp[i – 2][1] + dp[i – 2][2]).dp[i][1] = dp[i – 1][0] + dp[i – 1][2].dp[i][2] = dp[i – 1][0] + dp[i – 1][1].
dp[i][0] = (dp[i – 1][0] + dp[i – 2][0]+ dp[i – 2][1] + dp[i – 2][2]).
dp[i][1] = dp[i – 1][0] + dp[i – 1][2].
dp[i][2] = dp[i – 1][0] + dp[i – 1][1].
Based on the above observations, follow the steps below to solve the problem:
If the value of N is less than 3, then print N as the total number of ways.
Initialize a 2-dimensional array, say dp[][3] that stores all the states of the dp.
Consider the Base Case: dp[0][0] = dp[1][0] = dp[1][1] = dp[1][2] = 1.
Iterate over the given range [2, N] and using the variable i and perform the following transitions in the dp as:dp[i][0] equals (dp[i – 1][0] + dp[i – 2][0]+ dp[i – 2][1] + dp[i – 2][2]).dp[i][1] equals dp[i – 1][0] + dp[i – 1][2].dp[i][2] equals dp[i – 1][0] + dp[i – 1][1].
dp[i][0] equals (dp[i – 1][0] + dp[i – 2][0]+ dp[i – 2][1] + dp[i – 2][2]).
dp[i][1] equals dp[i – 1][0] + dp[i – 1][2].
dp[i][2] equals dp[i – 1][0] + dp[i – 1][1].
After completing the above steps, print the total number of ways stored in dp[N][0].
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ program for the above approach #include <bits/stdc++.h>using namespace std;const long long MOD = 1e9 + 7; // Function to find the total number// of ways to tile a 2*N board using// the given types of tileint numTilings(int N){    // If N is less than 3    if (N < 3) {        return N;    }     // Store all dp-states    vector<vector<long long> > dp(        N + 1, vector<long long>(3, 0));     // Base Case    dp[0][0] = dp[1][0] = 1;    dp[1][1] = dp[1][2] = 1;     // Traverse the range [2, N]    for (int i = 2; i <= N; i++) {         // Update the value of dp[i][0]        dp[i][0] = (dp[i - 1][0]                    + dp[i - 2][0]                    + dp[i - 2][1]                    + dp[i - 2][2])                   % MOD;         // Update the value of dp[i][1]        dp[i][1] = (dp[i - 1][0]                    + dp[i - 1][2])                   % MOD;         // Update the value of dp[i][2]        dp[i][2] = (dp[i - 1][0]                    + dp[i - 1][1])                   % MOD;    }     // Return the number of ways as    // the value of dp[N][0]    return dp[N][0];} // Driver Codeint main(){    int N = 3;    cout << numTilings(N);     return 0;}
// Java program for the above approachimport java.util.Arrays; class GFG{ public static long MOD = 1000000007l; // Function to find the total number// of ways to tile a 2*N board using// the given types of tilepublic static long numTilings(int N){         // If N is less than 3    if (N < 3)    {        return N;    }     // Store all dp-states    long[][] dp = new long[N + 1][3];     for(long[] row : dp)    {        Arrays.fill(row, 0);    }         // Base Case    dp[0][0] = dp[1][0] = 1;    dp[1][1] = dp[1][2] = 1;     // Traverse the range [2, N]    for(int i = 2; i <= N; i++)    {                 // Update the value of dp[i][0]        dp[i][0] = (dp[i - 1][0] + dp[i - 2][0] +                    dp[i - 2][1] + dp[i - 2][2]) % MOD;         // Update the value of dp[i][1]        dp[i][1] = (dp[i - 1][0] + dp[i - 1][2]) % MOD;         // Update the value of dp[i][2]        dp[i][2] = (dp[i - 1][0] + dp[i - 1][1]) % MOD;    }     // Return the number of ways as    // the value of dp[N][0]    return dp[N][0];} // Driver Codepublic static void main(String args[]){    int N = 3;         System.out.println(numTilings(N));}} // This code is contributed by gfgking
# Python3 program for the above approache9 + 7; # Function to find the total number# of ways to tile a 2*N board using# the given types of tileMOD = 1e9 + 7 def numTilings(N):         # If N is less than 3    if (N < 3):        return N     # Store all dp-states    dp = [[0] * 3 for i in range(N + 1)]     # Base Case    dp[0][0] = dp[1][0] = 1    dp[1][1] = dp[1][2] = 1     # Traverse the range [2, N]    for i in range(2, N + 1):         # Update the value of dp[i][0]        dp[i][0] = (dp[i - 1][0] +                    dp[i - 2][0] +                    dp[i - 2][1] +                    dp[i - 2][2]) % MOD         # Update the value of dp[i][1]        dp[i][1] = (dp[i - 1][0] +                    dp[i - 1][2]) % MOD         # Update the value of dp[i][2]        dp[i][2] = (dp[i - 1][0] +                    dp[i - 1][1]) % MOD     # Return the number of ways as    # the value of dp[N][0]    return int(dp[N][0]) # Driver CodeN = 3 print(numTilings(N)) # This code is contributed by gfgking
// C# program for the above approachusing System;using System.Collections.Generic; class GFG{ static int MOD = 1000000007; // Function to find the total number// of ways to tile a 2*N board using// the given types of tilestatic int numTilings(int N){    // If N is less than 3    if (N < 3) {        return N;    }     // Store all dp-states    int [,]dp = new int[N+1,3];     // Base Case    dp[0,0] = dp[1,0] = 1;    dp[1,1] = dp[1,2] = 1;     // Traverse the range [2, N]    for (int i = 2; i <= N; i++) {         // Update the value of dp[i,0]        dp[i,0] = (dp[i - 1,0]                    + dp[i - 2,0]                    + dp[i - 2,1]                    + dp[i - 2,2])                   % MOD;         // Update the value of dp[i,1]        dp[i,1] = (dp[i - 1,0]                    + dp[i - 1,2])                   % MOD;         // Update the value of dp[i,2]        dp[i,2] = (dp[i - 1,0]                    + dp[i - 1,1])                   % MOD;    }     // Return the number of ways as    // the value of dp[N,0]    return dp[N,0];} // Driver Codepublic static void Main(){    int N = 3;    Console.Write(numTilings(N));}} // This code is contributed by SURENDRA_GANGWAR.
<script>         // JavaScript program for the above approache9 + 7;         // Function to find the total number        // of ways to tile a 2*N board using        // the given types of tile        const MOD = 1e9 + 7;        function numTilings(N) {            // If N is less than 3            if (N < 3) {                return N;            }             // Store all dp-states            let dp = Array(N + 1).fill().map(() => Array(3).fill(0))             // Base Case            dp[0][0] = dp[1][0] = 1;            dp[1][1] = dp[1][2] = 1;             // Traverse the range [2, N]            for (let i = 2; i <= N; i++) {                 // Update the value of dp[i][0]                dp[i][0] = (dp[i - 1][0]                    + dp[i - 2][0]                    + dp[i - 2][1]                    + dp[i - 2][2])                    % MOD;                 // Update the value of dp[i][1]                dp[i][1] = (dp[i - 1][0]                    + dp[i - 1][2])                    % MOD;                 // Update the value of dp[i][2]                dp[i][2] = (dp[i - 1][0]                    + dp[i - 1][1])                    % MOD;            }             // Return the number of ways as            // the value of dp[N][0]            return dp[N][0];        }         // Driver Code         let N = 3;        document.write(numTilings(N));   // This code is contributed by Potta Lokesh    </script>
5
 
Time Complexity: O(N)Auxiliary Space: O(N)
lokeshpotta20
gfgking
SURENDRA_GANGWAR
Google
Dynamic Programming
Google
Dynamic Programming
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Maximum size square sub-matrix with all 1s
Optimal Substructure Property in Dynamic Programming | DP-2
Min Cost Path | DP-6
Optimal Binary Search Tree | DP-24
Box Stacking Problem | DP-22
Maximum Subarray Sum using Divide and Conquer algorithm
Greedy approach vs Dynamic programming
Maximum sum such that no two elements are adjacent
Word Break Problem | DP-32
Top 50 Dynamic Programming Coding Problems for Interviews