Domino and Tromino tiling problem
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 = 3
Output: 5
Explanation:
Below is the image to illustrate all the combinations:
Input: N = 1
Output: 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].
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].
- 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++
// 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 tile int 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 Code int main() { int N = 3; cout << numTilings(N); return 0; } |
Java
// Java program for the above approach import 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 tile public 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 Code public static void main(String args[]) { int N = 3 ; System.out.println(numTilings(N)); } } // This code is contributed by gfgking |
Python3
# 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 tile MOD = 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 Code N = 3 print (numTilings(N)) # This code is contributed by gfgking |
C#
// C# program for the above approach using 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 tile static 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 Code public static void Main() { int N = 3; Console.Write(numTilings(N)); } } // This code is contributed by SURENDRA_GANGWAR. |
Javascript
<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)
Easy Dp Algorithm Using Extra O(n) space.
C++
#include<bits/stdc++.h> #include<iostream> #define ll long long ll mod=1e9+7; using namespace std; void the_solver( int n){ vector<ll>dp(n+1,0); dp[0]=1; dp[1]=1;dp[2]=2;dp[3]=5; if (n<=3){ cout<<dp[n]<<endl; return ; } for ( int i=4;i<=n;i++){ dp[i]=2*(dp[i-1])+dp[i-3]; dp[i]%=mod; } cout<<dp[n]<<endl; return ; } signed main(){ int n=3; the_solver(n); return 0; } |
Java
//Java code for the above approach import java.util.*; class Main { static final long mod = 1000000000L + 7 ; // Function to solve problem static void theSolver( int n) { // Create an array of size n+1 to store the dp values long [] dp = new long [n + 1 ]; dp[ 0 ] = 1 ; dp[ 1 ] = 1 ; dp[ 2 ] = 2 ; dp[ 3 ] = 5 ; // If n is less than or equal to 3 if (n <= 3 ) { System.out.println(dp[n]); return ; } // Iterate through the array for ( int i = 4 ; i <= n; i++) { dp[i] = 2 * (dp[i - 1 ]) + dp[i - 3 ]; dp[i] %= mod; } System.out.println(dp[n]); return ; } public static void main(String[] args) { int n = 3 ; theSolver(n); } } |
Python3
mod = int ( 1e9 + 7 ) def the_solver(n): dp = [ 0 ] * (n + 1 ) dp[ 0 ] = 1 dp[ 1 ] = 1 dp[ 2 ] = 2 dp[ 3 ] = 5 if n < = 3 : print (dp[n]) return for i in range ( 4 , n + 1 ): dp[i] = 2 * dp[i - 1 ] + dp[i - 3 ] dp[i] % = mod print (dp[n]) return n = 3 the_solver(n) # This codez is contributed by lokeshpotta20. |
Javascript
function the_solver(n) { let dp= new Array(n).fill(0); dp[0]=1; dp[1]=1; dp[2]=2; dp[3]=5; if (n<=3) { document.write(dp[n]); return ; } for (let i=4;i<=n;i++){ dp[i]=2*(dp[i-1])+dp[i-3]; dp[i]%=mod; } document.write(dp[n]); return ; } let n=3; the_solver(n); |
C#
using System; using System.Linq; using System.Collections.Generic; class GFG { static int mod=1000000007; static void the_solver( int n) { int [] dp= new int [n+1]; for ( int i=0; i<n+1; i++) dp[i]=0; dp[0]=1; dp[1]=1; dp[2]=2; dp[3]=5; if (n<=3){ Console.WriteLine(dp[n]); return ; } for ( int i=4;i<=n;i++) { dp[i]=2*(dp[i-1])+dp[i-3]; dp[i]%=mod; } Console.WriteLine(dp[n]); return ; } static public void Main() { int n=3; the_solver(n); } } |
5
Time Complexity: O(N).
Auxiliary Space: O(N).
Please Login to comment...