Number of ways to paint K cells in 3 x N grid such that no P continuous columns are left unpainted

Given three integers N, P and K, the task is to find the number of ways of painting K cells of 3 x N grid such that no adjacent cells are painted and also no continuous P columns are left unpainted. 
Note: Diagonal cells are not considered as adjacent cells. 
Examples: 
 

Input: N = 1, P = 3, K = 1 
Output:
There are 3 ways to paint 1 cell in a 3 x 1 grid.
Input: N = 2, P = 2, K = 2 
Output:
There are 8 ways to paint 2 cells in a 3×2 grid. 
Combinations of cells those are painted is shown below – 
1) (0, 0) and (1, 1) 
2) (0, 0) and (2, 1) 
3) (0, 0) and (2, 0) 
4) (1, 0) and (0, 1) 
5) (1, 0) and (2, 1) 
6) (2, 0) and (0, 1) 
7) (2, 0) and (1, 1) 
8) (0, 1) and (2, 1) 
 

 

Approach: The idea is to use Dynamic Programming to solve this problem. As we know from the problem that 



column can be painted only when 

column is not painted. If 

column is not painted then we have following five cases – 
 

Therefore, using this fact we can solve this problem easily. 
Below is the implementation of the above approach: 
 

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation to find the
// number of ways to paint K cells of
// 3 x N grid such that No two adjacent
// cells are painted
 
#include <bits/stdc++.h>
using namespace std;
 
int mod = 1e9 + 7;
#define MAX 301
#define MAXP 3
#define MAXK 600
#define MAXPREV 4
 
int dp[MAX][MAXP + 1][MAXK][MAXPREV + 1];
 
// Visited array to keep track
// of which columns were painted
bool vis[MAX];
 
// Recursive Function to compute the
// number of ways to paint the K cells
// of the 3 x N grid
int helper(int col, int prevCol,
           int painted, int prev,
           int N, int P, int K)
{
 
    // Condition to check if total
    // cells painted are K
    if (painted >= K) {
        int continuousCol = 0;
        int maxContinuousCol = 0;
 
        // Check if any P continuous
        // columns were left unpainted
        for (int i = 0; i < N; i++) {
 
            if (vis[i] == false)
                continuousCol++;
            else {
                maxContinuousCol
                    = max(maxContinuousCol,
                          continuousCol);
                continuousCol = 0;
            }
        }
 
        maxContinuousCol = max(
            maxContinuousCol,
            continuousCol);
 
        // Condition to check if no P
        // continuous columns were
        // left unpainted
        if (maxContinuousCol < P)
            return 1;
 
        // return 0 if there are P
        // continuous columns are
        // left unpainted
        return 0;
    }
 
    // Condition to check if No
    // further cells can be
    // painted, so return 0
    if (col >= N)
        return 0;
 
    // if already calculated the value
    // return the val instead
    // of calculating again
    if (dp[col][prevCol][painted][prev] != -1)
        return dp[col][prevCol][painted][prev];
 
    int res = 0;
 
    // Previous column was not painted
    if (prev == 0) {
 
        // Column is painted so,
        // make vis[col]=true
        vis[col] = true;
        res += (helper(
                   col + 1, 0, painted + 1,
                   1, N, P, K))
               % mod;
 
        res += (helper(
                   col + 1, 0, painted + 1,
                   2, N, P, K))
               % mod;
 
        res += (helper(
                   col + 1, 0, painted + 1,
                   3, N, P, K))
               % mod;
 
        // Condition to check if the number
        // of cells to be painted is equal
        // to or more than 2, then we can
        // paint first and third row
        if (painted + 2 <= K) {
            res
                += (helper(
                       col + 1, 0, painted + 2,
                       4, N, P, K))
                   % mod;
        }
        vis[col] = false;
 
        // Condition to check if number of
        // previous continuous columns left
        // unpainted is less than P
        if (prevCol + 1 < P) {
            res
                += (helper(
                       col + 1, prevCol + 1,
                       painted, 0, N, P, K))
                   % mod;
        }
    }
 
    // Condition to check if first row
    // was painted in previous column
    else if (prev == 1) {
        vis[col] = true;
        res += (helper(
                   col + 1, 0, painted + 1,
                   2, N, P, K))
               % mod;
        res += (helper(
                   col + 1, 0, painted + 1,
                   3, N, P, K))
               % mod;
        vis[col] = false;
        if (prevCol + 1 < P) {
            res += (helper(
                       col + 1, prevCol + 1,
                       painted, 0, N, P, K))
                   % mod;
        }
    }
 
    // Condition to check if second row
    // was painted in previous column
    else if (prev == 2) {
        vis[col] = true;
        res += (helper(
                   col + 1, 0, painted + 1,
                   1, N, P, K))
               % mod;
        res += (helper(
                   col + 1, 0, painted + 1,
                   3, N, P, K))
               % mod;
 
        // Condition to check if the number
        // of cells to be painted is equal to
        // or more than 2, then we can
        // paint first and third row
        if (painted + 2 <= K) {
            res
                += (helper(
                       col + 1, 0, painted + 2,
                       4, N, P, K))
                   % mod;
        }
        vis[col] = false;
        if (prevCol + 1 < P) {
            res
                += (helper(
                       col + 1, prevCol + 1,
                       painted, 0, N, P, K))
                   % mod;
        }
    }
 
    // Condition to check if third row
    // was painted in previous column
    else if (prev == 3) {
        vis[col] = true;
        res += (helper(
                   col + 1, 0, painted + 1,
                   1, N, P, K))
               % mod;
        res += (helper(
                   col + 1, 0, painted + 1,
                   2, N, P, K))
               % mod;
        vis[col] = false;
        if (prevCol + 1 < P) {
            res += (helper(
                       col + 1, prevCol + 1,
                       painted, 0, N, P, K))
                   % mod;
        }
    }
 
    // Condition to check if first and
    // third row were painted
    // in previous column
    else {
        vis[col] = true;
        res += (helper(
                   col + 1, 0, painted + 1,
                   2, N, P, K))
               % mod;
        vis[col] = false;
        if (prevCol + 1 < P) {
            res += (helper(
                       col + 1, prevCol + 1,
                       painted, 0, N, P, K))
                   % mod;
        }
    }
 
    // Memoize the data and return the
    // Computed value
    return dp[col][prevCol][painted][prev]
           = res % mod;
}
 
// Function to find the number of
// ways to paint 3 x N grid
int solve(int n, int p, int k)
{
    // Set all values
    // of dp to -1;
    memset(dp, -1, sizeof(dp));
 
    // Set all values of Visited
    // array to false
    memset(vis, false, sizeof(vis));
 
    return helper(0, 0, 0, 0, n, p, k);
}
 
// Driver Code
int main()
{
 
    int N = 2, K = 2, P = 2;
    cout << solve(N, P, K) << endl;
 
    return 0;
}
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation to find the
// number of ways to paint K cells of
// 3 x N grid such that No two adjacent
// cells are painted
import java.util.*;
 
class GFG{
 
static int mod = (int)(1e9 + 7);
static final int MAX = 301;
static final int MAXP = 3;
static final int MAXK = 600;
static final int MAXPREV = 4;
 
static int [][][][]dp = new int[MAX][MAXP + 1][MAXK][MAXPREV + 1];
 
// Visited array to keep track
// of which columns were painted
static boolean []vis = new boolean[MAX];
 
// Recursive Function to compute the
// number of ways to paint the K cells
// of the 3 x N grid
static int helper(int col, int prevCol,
                  int painted, int prev,
                  int N, int P, int K)
{
     
    // Condition to check if total
    // cells painted are K
    if (painted >= K)
    {
        int continuousCol = 0;
        int maxContinuousCol = 0;
 
        // Check if any P continuous
        // columns were left unpainted
        for(int i = 0; i < N; i++)
        {
 
            if (vis[i] == false)
                continuousCol++;
            else
            {
                maxContinuousCol = Math.max(
                                   maxContinuousCol,
                                   continuousCol);
                continuousCol = 0;
            }
        }
 
        maxContinuousCol = Math.max(
                           maxContinuousCol,
                           continuousCol);
 
        // Condition to check if no P
        // continuous columns were
        // left unpainted
        if (maxContinuousCol < P)
            return 1;
 
        // return 0 if there are P
        // continuous columns are
        // left unpainted
        return 0;
    }
 
    // Condition to check if No
    // further cells can be
    // painted, so return 0
    if (col >= N)
        return 0;
 
    // If already calculated the value
    // return the val instead
    // of calculating again
    if (dp[col][prevCol][painted][prev] != -1)
        return dp[col][prevCol][painted][prev];
 
    int res = 0;
 
    // Previous column was not painted
    if (prev == 0)
    {
         
        // Column is painted so,
        // make vis[col]=true
        vis[col] = true;
        res += (helper(col + 1, 0,
                       painted + 1,
                       1, N, P, K)) % mod;
 
        res += (helper(col + 1, 0,
                       painted + 1,
                       2, N, P, K)) % mod;
 
        res += (helper(col + 1, 0,
                       painted + 1,
                       3, N, P, K)) % mod;
 
        // Condition to check if the number
        // of cells to be painted is equal
        // to or more than 2, then we can
        // paint first and third row
        if (painted + 2 <= K)
        {
            res += (helper(col + 1, 0,
                           painted + 2,
                           4, N, P, K)) % mod;
        }
        vis[col] = false;
 
        // Condition to check if number of
        // previous continuous columns left
        // unpainted is less than P
        if (prevCol + 1 < P)
        {
            res += (helper(col + 1,
                           prevCol + 1,
                           painted, 0,
                           N, P, K)) % mod;
        }
    }
 
    // Condition to check if first row
    // was painted in previous column
    else if (prev == 1)
    {
        vis[col] = true;
        res += (helper(col + 1, 0,
                       painted + 1,
                       2, N, P, K)) % mod;
        res += (helper(col + 1, 0,
                       painted + 1,
                       3, N, P, K)) % mod;
        vis[col] = false;
        if (prevCol + 1 < P)
        {
            res += (helper(col + 1,
                           prevCol + 1,
                           painted, 0,
                           N, P, K)) % mod;
        }
    }
 
    // Condition to check if second row
    // was painted in previous column
    else if (prev == 2)
    {
        vis[col] = true;
        res += (helper(col + 1, 0,
                       painted + 1,
                       1, N, P, K)) % mod;
        res += (helper(col + 1, 0,
                       painted + 1,
                       3, N, P, K)) % mod;
 
        // Condition to check if the number
        // of cells to be painted is equal to
        // or more than 2, then we can
        // paint first and third row
        if (painted + 2 <= K)
        {
            res += (helper(col + 1, 0,
                           painted + 2,
                           4, N, P, K)) % mod;
        }
        vis[col] = false;
        if (prevCol + 1 < P)
        {
            res += (helper(col + 1,
                           prevCol + 1,
                           painted, 0,
                           N, P, K)) % mod;
        }
    }
 
    // Condition to check if third row
    // was painted in previous column
    else if (prev == 3)
    {
        vis[col] = true;
        res += (helper(col + 1, 0,
                       painted + 1,
                       1, N, P, K)) % mod;
        res += (helper(col + 1, 0,
                       painted + 1,
                       2, N, P, K)) % mod;
        vis[col] = false;
        if (prevCol + 1 < P)
        {
            res += (helper(col + 1,
                           prevCol + 1,
                           painted, 0,
                           N, P, K)) % mod;
        }
    }
 
    // Condition to check if first and
    // third row were painted
    // in previous column
    else
    {
        vis[col] = true;
        res += (helper(col + 1, 0,
                       painted + 1,
                       2, N, P, K)) % mod;
        vis[col] = false;
        if (prevCol + 1 < P)
        {
            res += (helper(col + 1,
                           prevCol + 1,
                           painted, 0,
                           N, P, K)) % mod;
        }
    }
 
    // Memoize the data and return
    // the computed value
    return dp[col][prevCol][painted][prev] = res % mod;
}
 
// Function to find the number of
// ways to paint 3 x N grid
static int solve(int n, int p, int K)
{
     
    // Set all values
    // of dp to -1;
    for(int i = 0; i < MAX; i++)
        for(int j = 0; j < MAXP + 1; j++)
            for(int k = 0; k < MAXK; k++)
                for(int l = 0; l < MAXPREV + 1; l++)
                    dp[i][j][k][l] = -1;
 
    // Set all values of Visited
    // array to false
    Arrays.fill(vis, false);
 
    return helper(0, 0, 0, 0, n, p, K);
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 2, K = 2, P = 2;
     
    System.out.print(solve(N, P, K) + "\n");
}
}
 
// This code is contributed by Amit Katiyar
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation to find the
// number of ways to paint K cells of
// 3 x N grid such that No two adjacent
// cells are painted
using System;
class GFG{
  
static int mod = (int)(1e9 + 7);
static readonly int MAX = 301;
static readonly int MAXP = 3;
static readonly int MAXK = 600;
static readonly int MAXPREV = 4;
  
static int [,,,]dp = new int[MAX, MAXP + 1,
                             MAXK, MAXPREV + 1];
  
// Visited array to keep track
// of which columns were painted
static bool []vis = new bool[MAX];
  
// Recursive Function to compute the
// number of ways to paint the K cells
// of the 3 x N grid
static int helper(int col, int prevCol,
                int painted, int prev,
                int N, int P, int K)
{
      
    // Condition to check if total
    // cells painted are K
    if (painted >= K)
    {
        int continuousCol = 0;
        int maxContinuousCol = 0;
  
        // Check if any P continuous
        // columns were left unpainted
        for(int i = 0; i < N; i++)
        {
  
            if (vis[i] == false)
                continuousCol++;
            else
            {
                maxContinuousCol = Math.Max(
                                   maxContinuousCol,
                                   continuousCol);
                continuousCol = 0;
            }
        }
  
        maxContinuousCol = Math.Max(
                           maxContinuousCol,
                           continuousCol);
  
        // Condition to check if no P
        // continuous columns were
        // left unpainted
        if (maxContinuousCol < P)
            return 1;
  
        // return 0 if there are P
        // continuous columns are
        // left unpainted
        return 0;
    }
  
    // Condition to check if No
    // further cells can be
    // painted, so return 0
    if (col >= N)
        return 0;
  
    // If already calculated the value
    // return the val instead
    // of calculating again
    if (dp[col, prevCol, painted, prev] != -1)
        return dp[col, prevCol, painted, prev];
  
    int res = 0;
  
    // Previous column was not painted
    if (prev == 0)
    {
          
        // Column is painted so,
        // make vis[col]=true
        vis[col] = true;
        res += (helper(col + 1, 0,
                       painted + 1,
                       1, N, P, K)) % mod;
  
        res += (helper(col + 1, 0,
                       painted + 1,
                       2, N, P, K)) % mod;
  
        res += (helper(col + 1, 0,
                       painted + 1,
                       3, N, P, K)) % mod;
  
        // Condition to check if the number
        // of cells to be painted is equal
        // to or more than 2, then we can
        // paint first and third row
        if (painted + 2 <= K)
        {
            res += (helper(col + 1, 0,
                           painted + 2,
                           4, N, P, K)) % mod;
        }
        vis[col] = false;
  
        // Condition to check if number of
        // previous continuous columns left
        // unpainted is less than P
        if (prevCol + 1 < P)
        {
            res += (helper(col + 1,
                           prevCol + 1,
                           painted, 0,
                           N, P, K)) % mod;
        }
    }
  
    // Condition to check if first row
    // was painted in previous column
    else if (prev == 1)
    {
        vis[col] = true;
        res += (helper(col + 1, 0,
                       painted + 1,
                       2, N, P, K)) % mod;
        res += (helper(col + 1, 0,
                       painted + 1,
                       3, N, P, K)) % mod;
        vis[col] = false;
        if (prevCol + 1 < P)
        {
            res += (helper(col + 1,
                           prevCol + 1,
                           painted, 0,
                           N, P, K)) % mod;
        }
    }
  
    // Condition to check if second row
    // was painted in previous column
    else if (prev == 2)
    {
        vis[col] = true;
        res += (helper(col + 1, 0,
                       painted + 1,
                       1, N, P, K)) % mod;
        res += (helper(col + 1, 0,
                       painted + 1,
                       3, N, P, K)) % mod;
  
        // Condition to check if the number
        // of cells to be painted is equal to
        // or more than 2, then we can
        // paint first and third row
        if (painted + 2 <= K)
        {
            res += (helper(col + 1, 0,
                           painted + 2,
                           4, N, P, K)) % mod;
        }
        vis[col] = false;
        if (prevCol + 1 < P)
        {
            res += (helper(col + 1,
                           prevCol + 1,
                           painted, 0,
                           N, P, K)) % mod;
        }
    }
  
    // Condition to check if third row
    // was painted in previous column
    else if (prev == 3)
    {
        vis[col] = true;
        res += (helper(col + 1, 0,
                       painted + 1,
                       1, N, P, K)) % mod;
        res += (helper(col + 1, 0,
                       painted + 1,
                       2, N, P, K)) % mod;
        vis[col] = false;
        if (prevCol + 1 < P)
        {
            res += (helper(col + 1,
                           prevCol + 1,
                           painted, 0,
                           N, P, K)) % mod;
        }
    }
  
    // Condition to check if first and
    // third row were painted
    // in previous column
    else
    {
        vis[col] = true;
        res += (helper(col + 1, 0,
                       painted + 1,
                       2, N, P, K)) % mod;
        vis[col] = false;
        if (prevCol + 1 < P)
        {
            res += (helper(col + 1,
                           prevCol + 1,
                           painted, 0,
                           N, P, K)) % mod;
        }
    }
  
    // Memoize the data and return
    // the computed value
    return dp[col, prevCol, painted, prev] = res % mod;
}
  
// Function to find the number of
// ways to paint 3 x N grid
static int solve(int n, int p, int K)
{
      
    // Set all values
    // of dp to -1;
    for(int i = 0; i < MAX; i++)
        for(int j = 0; j < MAXP + 1; j++)
            for(int k = 0; k < MAXK; k++)
                for(int l = 0; l < MAXPREV + 1; l++)
                    dp[i, j, k, l] = -1;
  
    // Set all values of Visited
    // array to false
    for(int i = 0; i < vis.Length; i++)
        vis[i] = false;
  
    return helper(0, 0, 0, 0, n, p, K);
}
  
// Driver Code
public static void Main(String[] args)
{
    int N = 2, K = 2, P = 2;
      
    Console.Write(solve(N, P, K) + "\n");
}
}
  
// This code is contributed by Rohit_ranjan
chevron_right

Output: 
8


 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




Article Tags :