Given two positive integers N and C. There is a 2*N matrix where each cell of the matrix can be colored in 0 or 1. The task is to find number of ways, the 2*N matrix is formed having exactly c components.
A cell is said to be in the same component with the other cell if it shares a side with the other cell (immediate neighbor) and is of the same color.
Examples:
Input: N = 2, C = 1
Output: 2
Explanation:
C = 1 can be possible when all the cells of the matrix are colored in the same color.
We have 2 choices for coloring 0 and 1. Hence the answer is 2.
Input: N = 1, C = 2
Output: 2
Approach: The idea to solve this problem is using Dynamic Programming. Construct a 4D DP matrix of
Each cell of the matrix dp[i][j][row1][row2] gives the number of ways of having j components in i columns when arrangement in the last column is row1, row2. If current subproblem has been evaluated i.e dp[column][component][row1][row2] != -1, then use this result, else recursively compute the value.
- Base Case: When the number of columns becomes greater than N, then return 0. If the number of columns becomes equal to N then the answer depends on the number of components. If the components are equal to C then return 1 else return 0.
-
Case 1 : When previous column has the same color ({0, 0} or {1, 1}) in its row.
In this case, the components will increase by 1 if the current column has different values in its rows ({0, 1} or {1, 0}). The components will also increase by 1 if the current column has the opposite color but with the same value in its rows. That is the current column has {1, 1} when previous column has {0, 0}. or the current column has {0, 0} when previous column has {1, 1} . The components remain the same when the current column has the same combination as that of previous column. -
Case 2 : When previous column has the different color ({0, 1} or {1, 0}) in its row.
In this case, the components will increase by 2 if the current column has entirely opposite combination as that of its previous column. That is when the current column is {1, 0} and the previous column is {0, 1}. or the current column is {0, 1} and the previous column is {1, 0} . In all other cases, components remain same.
Below is the implementation of the above approach:
// C++ implementation to find the // number of ways to make exactly // C components in a 2 * N matrix #include <bits/stdc++.h> using namespace std;
// row1 and row2 are one // when both are same colored int n, k;
int dp[1024][2048][2][2];
// Function to find the number of // ways to make exactly C components // in a 2 * N matrix int Ways( int col, int comp,
int row1, int row2)
{ // if No of components
// at any stage exceeds
// the given number
// then base case
if (comp > k)
return 0;
if (col > n) {
if (comp == k)
return 1;
else
return 0;
}
// Condition to check
// if already visited
if (dp[col][comp][row1][row2] != -1)
return dp[col][comp][row1][row2];
// if not visited previously
else {
int ans = 0;
// At the first column
if (col == 1) {
// color {white, white} or
// {black, black}
ans
= (ans
+ Ways(col + 1, comp + 1, 0, 0)
+ Ways(col + 1, comp + 1, 1, 1));
// Color {white, black} or
// {black, white}
ans
= (ans
+ Ways(col + 1, comp + 2, 0, 1)
+ Ways(col + 1, comp + 2, 1, 0));
}
else {
// If previous both
// rows have same color
if ((row1 && row2)
|| (!row1 && !row2)) {
// Fill with {same, same} and
// {white, black} and {black, white}
ans = (((ans
+ Ways(col + 1, comp + 1, 0, 0))
+ Ways(col + 1, comp + 1, 1, 0))
+ Ways(col + 1, comp + 1, 0, 1));
// Fill with same without
// increase in component
// as it has been
// counted previously
ans = (ans
+ Ways(col + 1, comp, 1, 1));
}
// When previous rows
// had {white, black}
if (row1 && !row2) {
ans = (((ans
+ Ways(col + 1, comp, 0, 0))
+ Ways(col + 1, comp, 1, 1))
+ Ways(col + 1, comp, 1, 0));
ans = (ans
+ Ways(col + 1, comp + 2, 0, 1));
}
// When previous rows
// had {black, white}
if (!row1 && row2) {
ans = (((ans
+ Ways(col + 1, comp, 0, 0))
+ Ways(col + 1, comp, 1, 1))
+ Ways(col + 1, comp, 0, 1));
ans = (ans
+ Ways(col + 1, comp + 2, 1, 0));
}
}
// Memoization
return dp[col][comp][row1][row2] = ans;
}
} // Driver Code signed main()
{ n = 2;
k = 1;
memset (dp, -1, sizeof (dp));
// Initially at first column
// with 0 components
cout << Ways(1, 0, 0, 0);
return 0;
} |
// Java implementation to find the // number of ways to make exactly // C components in a 2 * N matrix class GFG{
// row1 and row2 are one // when both are same colored static int n, k;
static int [][][][]dp = new int [ 1024 ][ 2048 ][ 2 ][ 2 ];
// Function to find the number of // ways to make exactly C components // in a 2 * N matrix static int Ways( int col, int comp,
int row1, int row2)
{ // if No of components
// at any stage exceeds
// the given number
// then base case
if (comp > k)
return 0 ;
if (col > n)
{
if (comp == k)
return 1 ;
else
return 0 ;
}
// Condition to check
// if already visited
if (dp[col][comp][row1][row2] != - 1 )
return dp[col][comp][row1][row2];
// if not visited previously
else
{
int ans = 0 ;
// At the first column
if (col == 1 )
{
// color {white, white} or
// {black, black}
ans = (ans + Ways(col + 1 , comp + 1 , 0 , 0 ) +
Ways(col + 1 , comp + 1 , 1 , 1 ));
// Color {white, black} or
// {black, white}
ans = (ans + Ways(col + 1 , comp + 2 , 0 , 1 ) +
Ways(col + 1 , comp + 2 , 1 , 0 ));
}
else
{
// If previous both
// rows have same color
if ((row1 > 0 && row2 > 0 ) ||
(row1 == 0 && row2 == 0 ))
{
// Fill with {same, same} and
// {white, black} and {black, white}
ans = (((ans +
Ways(col + 1 , comp + 1 , 0 , 0 )) +
Ways(col + 1 , comp + 1 , 1 , 0 )) +
Ways(col + 1 , comp + 1 , 0 , 1 ));
// Fill with same without
// increase in component
// as it has been
// counted previously
ans = (ans +
Ways(col + 1 , comp, 1 , 1 ));
}
// When previous rows
// had {white, black}
if (row1 > 0 && row2 == 0 )
{
ans = (((ans +
Ways(col + 1 , comp, 0 , 0 )) +
Ways(col + 1 , comp, 1 , 1 )) +
Ways(col + 1 , comp, 1 , 0 ));
ans = (ans +
Ways(col + 1 , comp + 2 , 0 , 1 ));
}
// When previous rows
// had {black, white}
if (row1 == 0 && row2 > 0 )
{
ans = (((ans +
Ways(col + 1 , comp, 0 , 0 )) +
Ways(col + 1 , comp, 1 , 1 )) +
Ways(col + 1 , comp, 0 , 1 ));
ans = (ans +
Ways(col + 1 , comp + 2 , 1 , 0 ));
}
}
// Memoization
return dp[col][comp][row1][row2] = ans;
}
} // Driver Code public static void main(String[] args)
{ n = 2 ;
k = 1 ;
for ( int i = 0 ; i < 1024 ; i++)
for ( int j = 0 ; j < 2048 ; j++)
for ( int k = 0 ; k < 2 ; k++)
for ( int l = 0 ; l < 2 ; l++)
dp[i][j][k][l] = - 1 ;
// Initially at first column
// with 0 components
System.out.print(Ways( 1 , 0 , 0 , 0 ));
} } // This code is contributed by Rajput-Ji |
# Python implementation to find the # number of ways to make exactly # C components in a 2 * N matrix # row1 and row2 are one # when both are same colored n = 0
k = 0
dp = [[[[ - 1 for i in range ( 2 )] for j in range ( 2 )] for k in range ( 2048 )] for l in range ( 1024 )]
# Function to find the number of # ways to make exactly C components # in a 2 * N matrix def Ways(col, comp, row1, row2):
global n, k, dp
# if No of components
# at any stage exceeds
# the given number
# then base case
if (comp > k):
return 0
if (col > n):
if (comp = = k):
return 1
else :
return 0
# Condition to check
# if already visited
if (dp[col][comp][row1][row2] ! = - 1 ):
return dp[col][comp][row1][row2]
# if not visited previously
else :
ans = 0
# At the first column
if (col = = 1 ):
# color white, white or
# black, black
ans = (ans + Ways(col + 1 , comp + 1 , 0 , 0 ) + Ways(col + 1 , comp + 1 , 1 , 1 ))
# Color white, black or
# black, white
ans = (ans + Ways(col + 1 , comp + 2 , 0 , 1 ) + Ways(col + 1 , comp + 2 , 1 , 0 ))
else :
# If previous both
# rows have same color
if ((row1 and row2) or ( not row1 and not row2)):
# Fill with same, same and
# white, black and black, white
ans = (((ans + Ways(col + 1 , comp + 1 , 0 , 0 )) + Ways(col + 1 , comp + 1 , 1 , 0 )) + Ways(col + 1 , comp + 1 , 0 , 1 ))
# Fill with same without
# increase in component
# as it has been
# counted previously
ans = (ans + Ways(col + 1 , comp, 1 , 1 ))
# When previous rows
# had white, black
if (row1 and not row2):
ans = (((ans + Ways(col + 1 , comp, 0 , 0 )) + Ways(col + 1 , comp, 1 , 1 )) + Ways(col + 1 , comp, 1 , 0 ))
ans = (ans + Ways(col + 1 , comp + 2 , 0 , 1 ))
# When previous rows
# had black, white
if ( not row1 and row2):
ans = (((ans + Ways(col + 1 , comp, 0 , 0 )) + Ways(col + 1 , comp, 1 , 1 )) + Ways(col + 1 , comp, 0 , 1 ))
ans = (ans + Ways(col + 1 , comp + 2 , 1 , 0 ))
# Memoization
dp[col][comp][row1][row2] = ans
return dp[col][comp][row1][row2]
# Driver Code n = 2
k = 1
# Initially at first column # with 0 components print (Ways( 1 , 0 , 0 , 0 ))
# This code is contributed by Shubham Singh |
// C# implementation to find the // number of ways to make exactly // C components in a 2 * N matrix using System;
class GFG{
// row1 and row2 are one // when both are same colored static int n, k;
static int [,,,]dp = new int [ 1024, 2048, 2, 2 ];
// Function to find the number of // ways to make exactly C components // in a 2 * N matrix static int Ways( int col, int comp,
int row1, int row2)
{ // If No of components
// at any stage exceeds
// the given number
// then base case
if (comp > k)
return 0;
if (col > n)
{
if (comp == k)
return 1;
else
return 0;
}
// Condition to check
// if already visited
if (dp[ col, comp, row1, row2 ] != -1)
return dp[ col, comp, row1, row2 ];
// If not visited previously
else
{
int ans = 0;
// At the first column
if (col == 1)
{
// color {white, white} or
// {black, black}
ans = (ans + Ways(col + 1, comp + 1, 0, 0) +
Ways(col + 1, comp + 1, 1, 1));
// Color {white, black} or
// {black, white}
ans = (ans + Ways(col + 1, comp + 2, 0, 1) +
Ways(col + 1, comp + 2, 1, 0));
}
else
{
// If previous both
// rows have same color
if ((row1 > 0 && row2 > 0) ||
(row1 == 0 && row2 == 0))
{
// Fill with {same, same} and
// {white, black} and {black, white}
ans = (((ans +
Ways(col + 1, comp + 1, 0, 0)) +
Ways(col + 1, comp + 1, 1, 0)) +
Ways(col + 1, comp + 1, 0, 1));
// Fill with same without
// increase in component
// as it has been
// counted previously
ans = (ans +
Ways(col + 1, comp, 1, 1));
}
// When previous rows
// had {white, black}
if (row1 > 0 && row2 == 0)
{
ans = (((ans +
Ways(col + 1, comp, 0, 0)) +
Ways(col + 1, comp, 1, 1)) +
Ways(col + 1, comp, 1, 0));
ans = (ans +
Ways(col + 1, comp + 2, 0, 1));
}
// When previous rows
// had {black, white}
if (row1 == 0 && row2 > 0)
{
ans = (((ans +
Ways(col + 1, comp, 0, 0)) +
Ways(col + 1, comp, 1, 1)) +
Ways(col + 1, comp, 0, 1));
ans = (ans +
Ways(col + 1, comp + 2, 1, 0));
}
}
// Memoization
return dp[ col, comp, row1, row2 ] = ans;
}
} // Driver Code public static void Main(String[] args)
{ n = 2;
k = 1;
for ( int i = 0; i < 1024; i++)
for ( int j = 0; j < 2048; j++)
for ( int K = 0; K < 2; K++)
for ( int l = 0; l < 2; l++)
dp[ i, j, K, l ] = -1;
// Initially at first column
// with 0 components
Console.Write(Ways(1, 0, 0, 0));
} } // This code is contributed by Rajput-Ji |
<script> // Javascript implementation to find the // number of ways to make exactly // C components in a 2 * N matrix // row1 and row2 are one // when both are same colored var n, k;
var dp = new Array(1024).fill(0).map(() => new Array(2048).fill(0).map(() => new Array(2).fill(0).map(() => new Array(2).fill(0))));
// Function to find the number of // ways to make exactly C components // in a 2 * N matrix function Ways(col, comp, row1, row2)
{ // if No of components
// at any stage exceeds
// the given number
// then base case
if (comp > k)
return 0;
if (col > n)
{
if (comp == k)
return 1;
else
return 0;
}
// Condition to check
// if already visited
if (dp[col][comp][row1][row2] != -1)
return dp[col][comp][row1][row2];
// if not visited previously
else
{
var ans = 0;
// At the first column
if (col == 1)
{
// color {white, white} or
// {black, black}
ans = (ans + Ways(col + 1, comp + 1, 0, 0) +
Ways(col + 1, comp + 1, 1, 1));
// Color {white, black} or
// {black, white}
ans = (ans + Ways(col + 1, comp + 2, 0, 1) +
Ways(col + 1, comp + 2, 1, 0));
}
else
{
// If previous both
// rows have same color
if ((row1 > 0 && row2 > 0) ||
(row1 == 0 && row2 ==0))
{
// Fill with {same, same} and
// {white, black} and {black, white}
ans = (((ans +
Ways(col + 1, comp + 1, 0, 0)) +
Ways(col + 1, comp + 1, 1, 0)) +
Ways(col + 1, comp + 1, 0, 1));
// Fill with same without
// increase in component
// as it has been
// counted previously
ans = (ans +
Ways(col + 1, comp, 1, 1));
}
// When previous rows
// had {white, black}
if (row1 > 0 && row2 == 0)
{
ans = (((ans +
Ways(col + 1, comp, 0, 0)) +
Ways(col + 1, comp, 1, 1)) +
Ways(col + 1, comp, 1, 0));
ans = (ans +
Ways(col + 1, comp + 2, 0, 1));
}
// When previous rows
// had {black, white}
if (row1 ==0 && row2 > 0)
{
ans = (((ans +
Ways(col + 1, comp, 0, 0)) +
Ways(col + 1, comp, 1, 1)) +
Ways(col + 1, comp, 0, 1));
ans = (ans +
Ways(col + 1, comp + 2, 1, 0));
}
}
// Memoization
return dp[col][comp][row1][row2] = ans;
}
} // Driver Code n = 2; k = 1; for ( var i = 0; i < 1024; i++){
for ( var j = 0; j < 2048; j++){
for ( var K = 0; K < 2; K++){
for ( var l = 0; l < 2; l++){
dp[i][j][K][l] = -1;
}
}
}
} // Initially at first column // with 0 components document.write(Ways(1, 0, 0, 0)); // This code is contributed by Shubham Singh </script> |
Output:
2
Time Complexity: O(N*C)