Skip to content
Related Articles

Related Articles

Count ways to select N pairs of candies of distinct colors (Dynamic Programming + Bitmasking)
  • Difficulty Level : Medium
  • Last Updated : 15 Apr, 2021

Given an integer N representing the number of red and blue candies and a matrix mat[][] of size N * N, where mat[i][j] = 1 represents the existence of a pair between ith red candy and jth blue candy, the task is to find the count of ways to select N pairs of candies such that each pair contains distinct candies of different colors.

Examples:

Input: N = 2, mat[][] = { { 1, 1 }, { 1, 1 } } 
Output:
Explanation: 
Possible ways to select N (= 2) pairs of candies are { { (1, 1), (2, 2) }, { (1, 2), (2, 1) } }. 
Therefore, the required output is 2.

Input: N = 3, mat[][] = { { 0, 1, 1 }, { 1, 0, 1 }, { 1, 1, 1 } } 
Output:
Explanation: 
Possible ways to select N (= 3) pairs of candies are: { { (1, 2), (2, 1), (3, 3) }, { (1, 2), (2, 3), (3, 1) }, { (1, 3), (2, 1), (3, 2) } } 
Therefore, the required output is 2.

Naive Approach: The simplest approach to solve this problem is to generate all possible permutations of N pairs containing distinct candies of a different colors. Finally, print the count obtained.



Below is the implementation of the above approach:

C++14




// C++14 program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to count ways to select N distinct
// pairs of candies with different colours
int numOfWays(vector<vector<int>> a, int n,
                 int i, set<int> &blue)
{
     
    // If n pairs are selected
    if (i == n)
        return 1;
 
    // Stores count of ways
    // to select the i-th pair
    int count = 0;
 
    // Iterate over the range [0, n]
    for(int j = 0; j < n; j++)
    {
         
        // If pair (i, j) is not included
        if (a[i][j] == 1 && blue.find(j) == blue.end())
        {
            blue.insert(j);
            count += numOfWays(a, n, i + 1, blue);
            blue.erase(j);
        }
    }
    return count;
}
 
// Driver Code
int main()
{
    int n = 3;
    vector<vector<int>> mat = { { 0, 1, 1 },
                                { 1, 0, 1 },
                                { 1, 1, 1 } };
    set<int> mpp;
     
    cout << (numOfWays(mat, n, 0, mpp));
}
 
// This code is contributed by mohit kumar 29

Java




// Java program to implement
// the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG{
 
// Function to count ways to select N distinct
// pairs of candies with different colours
static int numOfWays(int a[][], int n, int i,
                     HashSet<Integer> blue)
{
     
    // If n pairs are selected
    if (i == n)
        return 1;
 
    // Stores count of ways
    // to select the i-th pair
    int count = 0;
 
    // Iterate over the range [0, n]
    for(int j = 0; j < n; j++)
    {
         
        // If pair (i, j) is not included
        if (a[i][j] == 1 && !blue.contains(j))
        {
            blue.add(j);
            count += numOfWays(a, n, i + 1, blue);
            blue.remove(j);
        }
    }
    return count;
}
 
// Driver Code
public static void main(String[] args)
{
    int n = 3;
    int mat[][] = { { 0, 1, 1 },
                    { 1, 0, 1 },
                    { 1, 1, 1 } };
    HashSet<Integer> mpp = new HashSet<>();
 
    System.out.println((numOfWays(mat, n, 0, mpp)));
}
}
 
// This code is contributed by Kingash

Python3




# Python3 program to implement
# the above approach
 
 
# Function to count ways to select N distinct
# pairs of candies with different colours
def numOfWays(a, n, i = 0, blue = []):
 
    # If n pairs are selected
    if i == n:
        return 1
 
    # Stores count of ways
    # to select the i-th pair
    count = 0
 
    # Iterate over the range [0, n]
    for j in range(n):
 
        # If pair (i, j) is not included
        if mat[i][j] == 1 and j not in blue:
            count += numOfWays(mat, n, i + 1,
                                blue + [j])
                                 
    return count
 
# Driver Code
if __name__ == "__main__":
    n = 3
    mat = [ [0, 1, 1],
            [1, 0, 1],
            [1, 1, 1] ]
    print(numOfWays(mat, n))

C#




// C# program to implement
// the above approach
using System;
using System.Collections.Generic;
 
class GFG{
     
// Function to count ways to select N distinct
// pairs of candies with different colours
static int numOfWays(int[,] a, int n, int i,
                     HashSet<int> blue)
{
     
    // If n pairs are selected
    if (i == n)
        return 1;
 
    // Stores count of ways
    // to select the i-th pair
    int count = 0;
 
    // Iterate over the range [0, n]
    for(int j = 0; j < n; j++)
    {
         
        // If pair (i, j) is not included
        if (a[i, j] == 1 && !blue.Contains(j))
        {
            blue.Add(j);
            count += numOfWays(a, n, i + 1, blue);
            blue.Remove(j);
        }
    }
    return count;
}
 
// Driver Code
public static void Main()
{
    int n = 3;
    int[,] mat = { { 0, 1, 1 },
                   { 1, 0, 1 },
                   { 1, 1, 1 } };
    HashSet<int> mpp = new HashSet<int>();
 
    Console.WriteLine((numOfWays(mat, n, 0, mpp)));
}
}
 
// This code is contributed by ukasp
Output: 
3

 

Time complexity: O(N!) 
Auxiliary Space: O(1)

Efficient Approach: The above approach can be optimized using Dynamic programming with Bit masking. Instead of generating all permutations of N blue candies, for every red candy, use a mask, where jth bit of mask checks if jth blue candy is available for selecting in the current pair or not. 
The recurrence relation to solve the problem is as follows:

If Kth bit of mask is unset and mat[i][k] = 1: 
dp[i + 1][j | (1 << k)] += dp[i][j]

where, (j | (1 << k)) marks the kth blue candy as selected.
dp[i][j] = Count of ways to make pairs between i red candy and N blue candies, where j is a permutation of N bit number range from 0 to 2N – 1).

Follow the steps below to solve the problem:

  • Initialize a 2D array, say dp[][], where dp[i][j] stores the count of ways to make pairs between i red candies and N blue candies. j represents a permutation of N bit number range from 0 to 2N-1.
  • Use the above recurrence relation and fill all possible dp states of the recurrence relation.
  • Finally, print the dp state where there are N red candies and N blue candies are selected, i.e. dp[i][2n-1].

Below is the implementation of the above approach:

Python3




# Python program to implement
# the above approach
  
  
# Function to count ways to select N distinct
# pairs of candies with different colors
def numOfWays(a, n):
 
 
    # dp[i][j]: Stores count of ways to make
    # pairs between i red candies and N blue candies
    dp = [[0]*((1 << n)+1) for _ in range(n + 1)]
 
    # If there is no red and blue candy,
    # the count of ways to make n pairs is 1
    dp[0][0] = 1
 
    # i: Stores count of red candy
    for i in range(n):
 
        # j generates a permutation of blue
        # candy of selected / not selected
        # as a binary number with n bits
        for j in range(1 << n):
 
            if dp[i][j] == 0:
                continue
    
            # Iterate over the range [0, n]   
            for k in range(n):
 
                # Create a mask with only
                # the k-th bit as set
                mask = 1 << k
                 
                # If Kth bit of mask is
                # unset  and mat[i][k] = 1
                if not(mask & j) and a[i][k]:
                    dp[i + 1][j | mask] += dp[i][j]
                     
         
                     
    # Return the dp states, where n red
    # and n blue candies are selected
    return dp[n][(1 << n)-1]
 
 
 
# Driver Code
if __name__ == "__main__":
    n = 3
    mat = [[0, 1, 1],
           [1, 0, 1],
           [1, 1, 1]]
    print(numOfWays(mat, n))
Output: 
3

 

Time Complexity:O(N2 * 2N) 
Auxiliary Space: O(N * 2N)

Attention reader! Don’t stop learning now. Get hold of all the important mathematical concepts for competitive programming with the Essential Maths for CP Course at a student-friendly price. To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

My Personal Notes arrow_drop_up
Recommended Articles
Page :