Open In App

Ways to fill N positions using M colors such that there are exactly K pairs of adjacent different colors

Improve
Improve
Like Article
Like
Save
Share
Report

Given three integers N, M and K. The task is to find the number of ways to fill N positions using M colors such that there are exactly K pairs of different adjacent colors.

Examples: 

Input: N = 3, M = 2, K = 1 
Output:
Let the colors be 1 and 2, so the ways are: 
1, 1, 2 
1, 2, 2 
2, 2, 1 
2, 1, 1 
The above 4 ways have exactly one pair of adjacent elements with different colors.

Input: N = 3, M = 3, K = 2 
Output: 12 

Approach: We can use Dynamic Programming with memoization to solve the above problem. There are N positions to fill, hence the recursive function will be composed of two calls, one if the next position is filled with the same color and the other if it is filled with a different color. Hence, the recursive calls will be: 

  • countWays(index + 1, cnt), if the next index is filled with the same color.
  • (m – 1) * countWays(index + 1, cnt + 1), if the next index is filled with a different color. The number of ways is multiplied by (m – 1).

The basic cases will be: 

  • If index = n, then a check for the value of cnt is done. If cnt = K then it is a possible way, hence return 1, else return 0.
  • To avoid repetitive calls, memoize the returned value in a 2-D array and return this value if the recursive call with the same parameters is done again.

Below is the implementation of the above approach: 

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
#define max 4
 
// Recursive function to find the required number of ways
int countWays(int index, int cnt, int dp[][max], int n, int m, int k)
{
 
    // When all positions are filled
    if (index == n) {
 
        // If adjacent pairs are exactly K
        if (cnt == k)
            return 1;
        else
            return 0;
    }
 
    // If already calculated
    if (dp[index][cnt] != -1)
        return dp[index][cnt];
 
    int ans = 0;
 
    // Next position filled with same color
    ans += countWays(index + 1, cnt, dp, n, m, k);
 
    // Next position filled with different color
    // So there can be m-1 different colors
    ans += (m - 1) * countWays(index + 1, cnt + 1, dp, n, m, k);
 
    return dp[index][cnt] = ans;
}
 
// Driver Code
int main()
{
    int n = 3, m = 3, k = 2;
    int dp[n + 1][max];
    memset(dp, -1, sizeof dp);
 
    cout << m * countWays(1, 0, dp, n, m, k);
}


Java




//Java implementation of the approach
class solution
{
static final int  max=4;
  
// Recursive function to find the required number of ways
static int countWays(int index, int cnt, int dp[][], int n, int m, int k)
{
  
    // When all positions are filled
    if (index == n) {
  
        // If adjacent pairs are exactly K
        if (cnt == k)
            return 1;
        else
            return 0;
    }
  
    // If already calculated
    if (dp[index][cnt] != -1)
        return dp[index][cnt];
  
    int ans = 0;
  
    // Next position filled with same color
    ans += countWays(index + 1, cnt, dp, n, m, k);
  
    // Next position filled with different color
    // So there can be m-1 different colors
    ans += (m - 1) * countWays(index + 1, cnt + 1, dp, n, m, k);
  
    return dp[index][cnt] = ans;
}
  
// Driver Code
public static void main(String args[])
{
    int n = 3, m = 3, k = 2;
    int dp[][]= new int [n + 1][max];
    for(int i=0;i<n+1;i++)
    for(int j=0;j<max;j++)
    dp[i][j]=-1;
  
    System.out.println(m * countWays(1, 0, dp, n, m, k));
}
}
//contributed by Arnab Kundu


Python 3




# Python 3 implementation of the approach
 
max = 4
 
# Recursive function to find the
# required number of ways
def countWays(index, cnt, dp, n, m, k):
 
    # When all positions are filled
    if (index == n) :
 
        # If adjacent pairs are exactly K
        if (cnt == k):
            return 1
        else:
            return 0
 
    # If already calculated
    if (dp[index][cnt] != -1):
        return dp[index][cnt]
 
    ans = 0
 
    # Next position filled with same color
    ans += countWays(index + 1, cnt, dp, n, m, k)
 
    # Next position filled with different color
    # So there can be m-1 different colors
    ans += (m - 1) * countWays(index + 1,
                               cnt + 1, dp, n, m, k)
 
    dp[index][cnt] = ans
    return dp[index][cnt]
 
# Driver Code
if __name__ == "__main__":
     
    n = 3
    m = 3
    k = 2
    dp = [[-1 for x in range(n + 1)]
              for y in range(max)]
 
    print(m * countWays(1, 0, dp, n, m, k))
 
# This code is contributed by ita_c


C#




// C# implementation of the approach
 
using System;
 
class solution
{
static int max=4;
 
// Recursive function to find the required number of ways
static int countWays(int index, int cnt, int [,]dp, int n, int m, int k)
{
 
    // When all positions are filled
    if (index == n) {
 
        // If adjacent pairs are exactly K
        if (cnt == k)
            return 1;
        else
            return 0;
    }
 
    // If already calculated
    if (dp[index,cnt] != -1)
        return dp[index,cnt];
 
    int ans = 0;
 
    // Next position filled with same color
    ans += countWays(index + 1, cnt, dp, n, m, k);
 
    // Next position filled with different color
    // So there can be m-1 different colors
    ans += (m - 1) * countWays(index + 1, cnt + 1, dp, n, m, k);
 
    return dp[index,cnt] = ans;
}
 
// Driver Code
public static void Main()
{
    int n = 3, m = 3, k = 2;
    int [,]dp= new int [n + 1,max];
    for(int i=0;i<n+1;i++)
        for(int j=0;j<max;j++)
            dp[i,j]=-1;
 
    Console.WriteLine(m * countWays(1, 0, dp, n, m, k));
}
// This code is contributed by Ryuga
}


Javascript




<script>
//Javascript implementation of the approach
 
let max=4;
 
// Recursive function to find the required number of ways
function countWays(index,cnt,dp,n,m,k)
{
    // When all positions are filled
    if (index == n) {
    
        // If adjacent pairs are exactly K
        if (cnt == k)
            return 1;
        else
            return 0;
    }
    
    // If already calculated
    if (dp[index][cnt] != -1)
        return dp[index][cnt];
    
    let ans = 0;
    
    // Next position filled with same color
    ans += countWays(index + 1, cnt, dp, n, m, k);
    
    // Next position filled with different color
    // So there can be m-1 different colors
    ans += (m - 1) * countWays(index + 1, cnt + 1, dp, n, m, k);
    
    return dp[index][cnt] = ans;
}
 
// Driver Code
let n = 3, m = 3, k = 2;
let dp=new Array(n+1);
for(let i=0;i<n+1;i++)
{   
    dp[i]=new Array(max);
    for(let j=0;j<max;j++)
        dp[i][j]=-1;
}   
document.write(m * countWays(1, 0, dp, n, m, k));   
     
// This code is contributed by rag2127
</script>


PHP




<?php
// PHP implementation of the approach
 
$GLOBALS['max'] = 4;
 
// Recursive function to find the
// required number of ways
function countWays($index, $cnt, $dp,
                         $n, $m, $k)
{
 
    // When all positions are filled
    if ($index == $n)
    {
 
        // If adjacent pairs are exactly K
        if ($cnt == $k)
            return 1;
        else
            return 0;
    }
 
    // If already calculated
    if ($dp[$index][$cnt] != -1)
        return $dp[$index][$cnt];
 
    $ans = 0;
 
    // Next position filled with same color
    $ans += countWays($index + 1, $cnt,
                      $dp, $n, $m, $k);
 
    // Next position filled with different color
    // So there can be m-1 different colors
    $ans += ($m - 1) * countWays($index + 1, $cnt + 1,
                                 $dp, $n, $m, $k);
 
    $dp[$index][$cnt] = $ans;
     
    return $dp[$index][$cnt];
}
 
// Driver Code
$n = 3;
$m = 3;
$k = 2;
$dp = array(array());
 
for($i = 0; $i < $n + 1; $i++)
    for($j = 0; $j < $GLOBALS['max']; $j++)
        $dp[$i][$j] = -1;
 
echo $m * countWays(1, 0, $dp, $n, $m, $k);
 
// This code is contributed by aishwarya.27
?>


Output

12




Time Complexity: O(n*4), as we are using recursion and the function will be called N times, where N is the number of positions to be filled.

Auxiliary Space: O(n*4), as we are using extra space for the dp matrix, where N is the number of positions to be filled.

Efficient approach : Using DP Tabulation method ( Iterative approach )

The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.

Steps to solve this problem :

  • Create a DP to store the solution of the subproblems and initialize it with 0.
  • Initialize the DP with base cases
  • Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
  • Return the final solution stored in m * dp[1][0].

Implementation :

C++




#include <bits/stdc++.h>
using namespace std;
#define max 4
  
int countWays(int n, int m, int k) {
    int dp[n + 1][max];
    memset(dp, 0, sizeof dp);
  
    // base case
    for(int cnt=0; cnt<=k; cnt++) {
        if(cnt == k) {
            dp[n][cnt] = 1;
        } else {
            dp[n][cnt] = 0;
        }
    }
  
    // fill the table using bottom-up approach
    for(int index=n-1; index>=1; index--) {
        for(int cnt=0; cnt<=k; cnt++) {
            int ans = 0;
  
            // if the current index is not selected
            ans += dp[index+1][cnt];
  
            // if the current index is selected
            if(cnt+1 <= k) {
                ans += (m-1) * dp[index+1][cnt+1];
            }
  
            dp[index][cnt] = ans;
        }
    }
  
    return m * dp[1][0];
}
  
// Driver Code
int main()
{
    int n = 3, m = 3, k = 2;
    cout << countWays(n, m, k);
}


Java




import java.util.Arrays;
 
public class Main {
    static int max = 4;
 
    static int countWays(int n, int m, int k) {
        int[][] dp = new int[n + 1][max];
        // Initialize the dp array with zeros
        for (int[] row : dp) {
            Arrays.fill(row, 0);
        }
 
        // Base case
        for (int cnt = 0; cnt <= k; cnt++) {
            if (cnt == k) {
                dp[n][cnt] = 1;
            } else {
                dp[n][cnt] = 0;
            }
        }
 
        // Fill the table using a bottom-up approach
        for (int index = n - 1; index >= 1; index--) {
            for (int cnt = 0; cnt <= k; cnt++) {
                int ans = 0;
 
                // If the current index is not selected
                ans += dp[index + 1][cnt];
 
                // If the current index is selected
                if (cnt + 1 <= k) {
                    ans += (m - 1) * dp[index + 1][cnt + 1];
                }
 
                dp[index][cnt] = ans;
            }
        }
 
        return m * dp[1][0];
    }
// Driver code
    public static void main(String[] args) {
        int n = 3, m = 3, k = 2;
        System.out.println(countWays(n, m, k));
    }
}


Python




def countWays(n, m, k):
    MAX = 4
    dp = [[0] * MAX for i in range(n + 1)]
  
    # base case
    for cnt in range(k + 1):
        if cnt == k:
            dp[n][cnt] = 1
        else:
            dp[n][cnt] = 0
  
    # fill the table using bottom-up approach
    for index in range(n - 1, 0, -1):
        for cnt in range(k + 1):
            ans = 0
  
            # if the current index is not selected
            ans += dp[index + 1][cnt]
  
            # if the current index is selected
            if cnt + 1 <= k:
                ans += (m - 1) * dp[index + 1][cnt + 1]
  
            dp[index][cnt] = ans
  
    return m * dp[1][0]
  
# Driver Code
if __name__ == "__main__":
    n, m, k = 3, 3, 2
    print(countWays(n, m, k))


C#




using System;
 
class WaysCount
{
    const int Max = 4;
 
    // Function to count ways of placing at most k items in n slots,
    // where each slot can accommodate m items.
    static int CountWays(int n, int m, int k)
    {
        int[,] dp = new int[n + 1, Max];
 
        // base case
        for (int cnt = 0; cnt <= k; cnt++)
        {
            if (cnt == k)
            {
                dp[n, cnt] = 1;
            }
            else
            {
                dp[n, cnt] = 0;
            }
        }
 
        // fill the table using bottom-up approach
        for (int index = n - 1; index >= 1; index--)
        {
            for (int cnt = 0; cnt <= k; cnt++)
            {
                int ans = 0;
 
                // if the current index is not selected
                ans += dp[index + 1, cnt];
 
                // if the current index is selected
                if (cnt + 1 <= k)
                {
                    ans += (m - 1) * dp[index + 1, cnt + 1];
                }
 
                dp[index, cnt] = ans;
            }
        }
 
        return m * dp[1, 0];
    }
 
    // Driver Code
    static void Main()
    {
        int n = 3, m = 3, k = 2;
        Console.WriteLine("Number of ways: " + CountWays(n, m, k));
    }
}


Javascript




function countWays(n, m, k) {
    // Initialize a 2D array for dynamic programming
    let dp = new Array(n + 1).fill(0).map(() => new Array(4).fill(0));
 
    // Base case
    for (let cnt = 0; cnt <= k; cnt++) {
        if (cnt === k) {
            dp[n][cnt] = 1;
        } else {
            dp[n][cnt] = 0;
        }
    }
 
    // Fill the table using a bottom-up approach
    for (let index = n - 1; index >= 1; index--) {
        for (let cnt = 0; cnt <= k; cnt++) {
            let ans = 0;
 
            // If the current index is not selected
            ans += dp[index + 1][cnt];
 
            // If the current index is selected
            if (cnt + 1 <= k) {
                ans += (m - 1) * dp[index + 1][cnt + 1];
            }
 
            dp[index][cnt] = ans;
        }
    }
 
    return m * dp[1][0];
}
 
// Driver Code
let n = 3, m = 3, k = 2;
console.log(countWays(n, m, k));


Output: 

12

 

Time Complexity: O(n*4)

Auxiliary Space: O(n*4)



Last Updated : 04 Dec, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads