
Problem Statement
In this problem, we are tasked with calculating the number of distinct ways to completely cover a 2 x n
board using two types of tiles: the 2 x 1
domino and the L-shaped tromino tile. Both tile types can be rotated as needed to fit on the board. Each cell on the board must be covered by a piece of a tile without overlapping, and no cell should be left uncovered. The uniqueness of a tiling configuration is determined by the fact that there should not exist a pair of adjacent cells that are exclusively covered in one tiling configuration and not in another. Given the potentially vast number of tiling configurations, the result should be returned modulo $10^9 + 7$.
Examples
Example 1
Input:
n = 3
Output:
5
Explanation:
The five different ways are show above.
Example 2
Input:
n = 1
Output:
1
Constraints
1 <= n <= 1000
Approach and Intuition
To understand how we can solve the problem of tiling a 2 x n
board, let's break down the process:
Base Cases:
- When
n = 1
, the board is2 x 1
. It can only be filled with one2 x 1
domino vertically. Hence, there is only one way. - For
n = 2
, considerations expand as tromino tiles come into play, adding more ways compared ton = 1
.
- When
Recursive Structure:
- For any larger board of width
n
, the possible configurations can be reduced into subproblems of smaller board widths. For instance, placing a single domino tile can reduce the problem to solving the number of ways to tile a2 x (n-1)
board. - Similarly, placement of a tromino affects two columns simultaneously and the remaining problem becomes tiling a
2 x (n-2)
board.
- For any larger board of width
Dynamic Programming Approach:
- By using a dynamic programming table, say
dp[i]
, wherei
represents the number of ways to tile a2 x i
board, we can build up solutions for larger boards based on previously computed smaller boards. - Initialization: Set
dp[1]
for a single domino vertical placement. Further settings likedp[0]
can be considered as an empty board scenario. - Fill in the
dp
table using the recursive reduction observations, keeping in mind how dominoes and trominos can be placed.
- By using a dynamic programming table, say
Modular Arithmetic:
- Given the constraints and possible outputs, calculate each step modulo $10^9 + 7` to prevent overflow and adhere to the problem's requirement.
Complexity Consideration:
- With the constraints of
n
up to1000
, a DP approach with O(n) time complexity (by populating thedp
array iteratively) is efficient and feasible.
- With the constraints of
Final Computation:
- After populating the
dp
table, the answer to the problem for a board of widthn
is simply found indp[n]
. This solution is calculated under the modulus to manage the size of the numbers throughout the computation.
- After populating the
Through this approach, we consider all possible placements and their combinations recursively while utilizing dynamic programming to efficiently compute the required number of unique tilings for a 2 x n
board.
Solutions
- C++
- Java
- Python
class Solution {
public:
int numOfTilings(int n) {
int MODULO = 1'000'000'007;
if (n <= 2) {
return n;
}
long currentTile = 5L;
long previousTile = 2L;
long tileBeforePrevious = 1L;
for (int i = 4; i < n + 1; ++i) {
long temp = previousTile;
previousTile = currentTile;
currentTile = (2 * currentTile + tileBeforePrevious) % MODULO;
tileBeforePrevious = temp;
}
return static_cast<int>(currentTile);
}
};
This C++ program solves the problem of counting the number of ways to tile a 2 x N board using dominoes (1 x 2 tiles) and trominoes (L-shaped tiles). The class Solution
includes the function numOfTilings
which takes an integer n
representing the length of the board.
- The function starts by defining
MODULO
to handle large numbers, ensuring that all arithmetic is done under modulo (1,000,000,007) to prevent overflow. - It handles base cases directly:
- If
n
is less than or equal to 2, the function returnsn
, as there are exactlyn
ways to tile a 2xN board whenN
is either 1 or 2.
- If
- For
n > 2
, it initializes the variablescurrentTile
,previousTile
, andtileBeforePrevious
to 5, 2, and 1 respectively. These variables will track the number of ways to tile smaller sections of the board and use them to build up to the solution forn
. - The for-loop runs from 4 to
n + 1
, updating:currentTile
as the sum of twice thecurrentTile
andtileBeforePrevious
, all under modulo operation.- The values of
previousTile
andtileBeforePrevious
get adjusted to shift the sequence forward.
- At the end of the loop,
currentTile
holds the number of ways to tile the board of size2 x n
. This value is cast to anint
and returned.
The approach efficiently calculates the result using dynamic programming principles to build up the solution iteratively while leveraging modulo arithmetic to manage large intermediate results.
class Solution {
public int tilingWays(int tiles) {
final int MODULO = 1_000_000_007;
if (tiles <= 2) {
return tiles;
}
long current = 5L;
long prev = 2;
long prevPrev = 1;
for (int i = 4; i <= tiles; ++i) {
long temp = prev;
prev = current;
current = (2 * current + prevPrev) % MODULO;
prevPrev = temp;
}
return (int) (current % MODULO);
}
}
In the given Java program, the problem of "Domino and Tromino Tiling" is addressed with a dynamic programming approach. Here's a breakdown of how the solution method tilingWays
calculates the number of ways to tile a board of length tiles
using dominos and trominos.
An integer constant
MODULO
is defined to ensure that the result is computed within a mod of 1,000,000,007, which prevents overflow issues and keeps numbers manageable.Edge cases for small values of
tiles
are directly returned at the beginning. Iftiles
is 2 or less, the function returnstiles
itself, as 1 and 2 can only be tiled in 1 and 2 ways, respectively.Initialize
current
,prev
(previous), andprevPrev
(second previous) to represent the number of ways to tile smaller configurations. This setup helps to build the solution iteratively.A loop starts from 4 up to
tiles
. Within each iteration:- The
current
value is calculated based on 2 times the current number of ways plus the number of ways two steps back (prevPrev
). This recursion relation reflects the addition of new tiles to previously solved configurations. prevPrev
is updated to the oldprev
.prev
is updated to the current value before updating it.
- The
Finally, the result is adjusted with the modulus operation to ensure it respects the
MODULO
limitation.
This algorithm efficiently computes the tiling ways using the properties of dynamic programming to reuse past calculations, reducing the time complexity compared to naive methods.
class Solution:
def countTilings(self, n: int) -> int:
MODULO = 1_000_000_007
if n <= 2:
return n
current = 5
last = 2
lastTwo = 1
for iteration in range(4, n + 1):
temp = last
last = current
current = (2 * current + lastTwo) % MODULO
lastTwo = temp
return current
In the provided Python solution, the function countTilings
calculates the number of ways to tile a 2 x n
board using dominos and trominos. The function employs dynamic programming, leveraging memoization to efficiently store and calculate results.
Here's a breakdown of how the solution works:
Initial Conditions:
- When
n
is 1 or 2, the result is direct:1
forn = 1
and2
forn = 2
. - The variable
MODULO
constrains the result within a range, specifically1,000,000,007
, to manage larger numbers and avoid overflow issues.
- When
Dynamic Programming Transition:
- Starting from
n = 3
, the function initializes three variablescurrent
,last
, andlastTwo
, corresponding to the number of ways to tile2 x (n-1)
and2 x (n-2)
boards, respectively. - As the loop proceeds from
n = 4
onward,current
is updated based on the previous two states (last
,lastTwo
), considering the unique ways dominos and trominos can fit into the board layout.
- Starting from
Loop Execution:
- The loop updates the values of
current
,last
, andlastTwo
by iterating from 4 ton
:lastTwo
holds the number of ways to tile the board of sizen-2
.last
temporarily holds the value ofcurrent
before current is updated, ensuring that the previous state is kept for the next calculation.
- The result for each iteration, represented as
current
, is adjusted for modulo1_000,000,007
to maintain the results within the specified limit.
- The loop updates the values of
The functionality of the solution leans on the mathematical relationships between states (current, last, and lastTwo) to build up to the solution for a 2 x n
board size, ensuring efficiency and avoiding calculation of redundant states. With these steps, the program provides an effective way to understand dynamic transitions in domino and tromino tiling problems.
No comments yet.