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: 2
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: 3
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 different colors. Finally, print the count obtained.
Below is the implementation of the above approach:
C++14
#include <bits/stdc++.h>
using namespace std;
int numOfWays(vector<vector< int >> a, int n,
int i, set< int > &blue)
{
if (i == n)
return 1;
int count = 0;
for ( int j = 0; j < n; j++)
{
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;
}
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));
}
|
Java
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG{
static int numOfWays( int a[][], int n, int i,
HashSet<Integer> blue)
{
if (i == n)
return 1 ;
int count = 0 ;
for ( int j = 0 ; j < n; j++)
{
if (a[i][j] == 1 && !blue.contains(j))
{
blue.add(j);
count += numOfWays(a, n, i + 1 , blue);
blue.remove(j);
}
}
return count;
}
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)));
}
}
|
Python3
def numOfWays(a, n, i = 0 , blue = []):
if i = = n:
return 1
count = 0
for j in range (n):
if mat[i][j] = = 1 and j not in blue:
count + = numOfWays(mat, n, i + 1 ,
blue + [j])
return count
if __name__ = = "__main__" :
n = 3
mat = [ [ 0 , 1 , 1 ],
[ 1 , 0 , 1 ],
[ 1 , 1 , 1 ] ]
print (numOfWays(mat, n))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int numOfWays( int [,] a, int n, int i,
HashSet< int > blue)
{
if (i == n)
return 1;
int count = 0;
for ( int j = 0; j < n; j++)
{
if (a[i, j] == 1 && !blue.Contains(j))
{
blue.Add(j);
count += numOfWays(a, n, i + 1, blue);
blue.Remove(j);
}
}
return count;
}
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)));
}
}
|
Javascript
<script>
function numOfWays(a, n, i, blue)
{
if (i == n)
return 1;
let count = 0;
for (let j = 0; j < n; j++)
{
if (a[i][j] == 1 && !blue.has(j))
{
blue.add(j);
count += numOfWays(a, n, i + 1, blue);
blue. delete (j);
}
}
return count;
}
let n = 3;
let mat = [ [ 0, 1, 1 ],
[ 1, 0, 1 ],
[ 1, 1, 1 ] ];
let mpp = new Set();
document.write(numOfWays(mat, n, 0, mpp));
</script>
|
Time complexity: O(N!)
Auxiliary Space: O(N) where N is recursion stack space
Efficient Approach: The above approach can be optimized for 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 the current pair or not.
The recurrence relation to solving 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 ranging 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 ranging 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:
C++
#include <iostream>
#include <cstring>
using namespace std;
int numOfWays( int a[][100], int n)
{
int dp[100][1 << n];
memset (dp, 0, sizeof (dp));
dp[0][0] = 1;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < (1 << n); j++) {
if (dp[i][j] == 0) {
continue ;
}
for ( int k = 0; k < n; k++) {
int mask = (1 << k);
if ((mask & j) == 0 && a[i][k] == 1) {
dp[i + 1][j | mask] += dp[i][j];
}
}
}
}
return dp[n][(1 << n) - 1];
}
int main()
{
int n = 3;
int mat[100][100] = {
{0, 1, 1},
{1, 0, 1},
{1, 1, 1}
};
cout<<numOfWays(mat, n);
return 0;
}
|
Java
import java.util.Arrays;
public class Main {
static int numOfWays( int [][] a, int n) {
int [][] dp = new int [n + 1 ][ 1 << n + 1 ];
dp[ 0 ][ 0 ] = 1 ;
for ( int i = 0 ; i < n; i++) {
for ( int j = 0 ; j < ( 1 << n); j++) {
if (dp[i][j] == 0 ) {
continue ;
}
for ( int k = 0 ; k < n; k++) {
int mask = ( 1 << k);
if ((mask & j) == 0 && a[i][k] == 1 ) {
dp[i + 1 ][j | mask] += dp[i][j];
}
}
}
}
return dp[n][( 1 << n) - 1 ];
}
public static void main(String[] args) {
int n = 3 ;
int [][] mat = new int [][] {
{ 0 , 1 , 1 },
{ 1 , 0 , 1 },
{ 1 , 1 , 1 }
};
System.out.println(numOfWays(mat, n));
}
}
|
Python3
def numOfWays(a, n):
dp = [[ 0 ] * (( 1 << n) + 1 ) for _ in range (n + 1 )]
dp[ 0 ][ 0 ] = 1
for i in range (n):
for j in range ( 1 << n):
if dp[i][j] = = 0 :
continue
for k in range (n):
mask = 1 << k
if not (mask & j) and a[i][k]:
dp[i + 1 ][j | mask] + = dp[i][j]
return dp[n][( 1 << n) - 1 ]
if __name__ = = "__main__" :
n = 3
mat = [[ 0 , 1 , 1 ],
[ 1 , 0 , 1 ],
[ 1 , 1 , 1 ]]
print (numOfWays(mat, n))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int numOfWays( int [][] a, int n){
int [][] dp = new int [n+1][];
for ( int i = 0 ; i <= n ; i++){
dp[i] = new int [(1 << n)+1];
}
dp[0][0] = 1;
for ( int i = 0 ; i < n ; i++){
for ( int j = 0 ; j < (1 << n) ; j++){
if (dp[i][j] == 0){
continue ;
}
for ( int k = 0 ; k < n ; k++){
int mask = (1 << k);
if ((mask & j) == 0 && a[i][k] == 1){
dp[i + 1][j | mask] += dp[i][j];
}
}
}
}
return dp[n][(1 << n)-1];
}
public static void Main( string [] args){
int n = 3;
int [][] mat = new int [3][];
mat[0] = new int []{0, 1, 1};
mat[1] = new int []{1, 0, 1};
mat[2] = new int []{1, 1, 1};
Console.Write(numOfWays(mat, n));
}
}
|
Javascript
function numOfWays(a, n) {
let dp = Array.from({ length: n + 1 },
() => Array.from({ length: (1 << n) + 1 }, () => 0));
dp[0][0] = 1;
for (let i = 0; i < n; i++) {
for (let j = 0; j < (1 << n); j++) {
if (dp[i][j] === 0) continue ;
for (let k = 0; k < n; k++) {
let mask = 1 << k;
if (!(mask & j) && a[i][k]) {
dp[i + 1][j | mask] += dp[i][j];
}
}
}
}
return dp[n][(1 << n) - 1];
}
let n = 3;
let mat = [[0, 1, 1],
[1, 0, 1],
[1, 1, 1]]
console.log(numOfWays(mat, n))
|
Time Complexity:O(N2 * 2N)
Auxiliary Space: O(N * 2N)