Consider the below problems statement. There are 100 different types of caps each having a unique id from 1 to 100. Also, there are ānā persons each having a collection of a variable number of caps. One day all of these persons decide to go in a party wearing a cap but to look unique they decided that none of them will wear the same type of cap. So, count the total number of arrangements or ways such that none of them is wearing the same type of cap. Constraints: 1 <= n <= 10 Example:
The first line contains the value of n, next n lines contain collections
of all the n persons.
Input:
3
5 100 1 // Collection of the first person.
2 // Collection of the second person.
5 100 // Collection of the third person.
Output:
4
Explanation: All valid possible ways are (5, 2, 100), (100, 2, 5),
(1, 2, 5) and (1, 2, 100)
Since, number of ways could be large, so output modulo 1000000007Ā
We strongly recommend you to minimize your browser and try this yourself first.Ā
A Simple Solution is to try all possible combinations. Start by picking the first element from the first set, marking it as visited and recur for remaining sets. It is basically a Backtracking based solution.Ā
A better solution is to use Bitmasking and DP.Ā
Let us first introduce Bitmasking.Ā
What is Bitmasking?Ā
Suppose we have a collection of elements which are numbered from 1 toĀ N. If we want to represent a subset of this set then it can be encoded by a sequence ofĀ NĀ bits (we usually call this sequence a āmaskā). In our chosen subset the i-th element belongs to it if and only if theĀ i-th bit of the mask is set i.e., it equals to 1. For example, the mask 10000101Ā means that the subset of the setĀ [1⦠8]Ā consists of elements 1, 3 and 8. We know that for a set of N elements there are total 2N subsets thus 2N masks are possible, one representing each subset. Each mask is, in fact, an integer number written in binary notation.Ā
Our main methodology is to assign a value to each mask (and, therefore, to each subset) and thus calculate the values for new masks using values of the already computed masks. Usually our main target is to calculate value/solution for the complete set i.e., for mask 11111111. Normally, to find the value for a subsetĀ XĀ we remove an element in every possible way and use values for obtained subsetsĀ Xā1, Xā2⦠,XākĀ to compute the value/solution forĀ X. This means that the values forĀ XāiĀ must have been computed already, so we need to establish an ordering in which masks will be considered. Itās easy to see that the natural ordering will do: go over masks in increasing order of corresponding numbers. Also, We sometimes, start with the empty subset X and we add elements in every possible way and use the values of obtained subsets Xā1, Xā2⦠,Xāk to compute the value/solution forĀ X. We mostly use the following notations/operations on masks: bit(i, mask)Ā ā theĀ i-th bit ofĀ mask count(mask)Ā ā the number of non-zero bits in the mask first(mask)Ā ā the number of the lowest non-zero bit in the mask set(i, mask) ā set the ith bit in the mask check(i, mask) ā check the ith bit in the maskĀ
How is this problem solved using Bitmasking + DP? The idea is to use the fact that there are upto 10 persons. So we can use an integer variable as a bitmask to store which person is wearing a cap and which is not.
Let i be the current cap number (caps from 1 to i-1 are already
processed). Let integer variable mask indicates that the persons w
earing and not wearing caps. If i'th bit is set in mask, then
i'th person is wearing a cap, else not.
// consider the case when ith cap is not included
// in the arrangement
countWays(mask, i) = countWays(mask, i+1) +
// when ith cap is included in the arrangement
// so, assign this cap to all possible persons
// one by one and recur for remaining persons.
ā countWays(mask | (1 << j), i+1)
for every person j that can wear cap i
Note that the expression "mask | (1 << j)" sets j'th bit in mask.
And a person can wear cap i if it is there in the person's cap list
provided as input.
If we draw the complete recursion tree, we can observe that many subproblems are solved again and again. So we use Dynamic Programming. A table dp[][] is used such that in every entry dp[i][j], i is mask and j is cap number. Since we want to access all persons that can wear a given cap, we use an array of vectors, capList[101]. A value capList[i] indicates the list of persons that can wear cap i.Ā
Below is the implementation of above idea.Ā
C++
// C++ program to find number of ways to wear hats#include<bits/stdc++.h>#define MOD 1000000007using namespace std;Ā
// capList[i]'th vector contains the list of persons having a cap with id i// id is between 1 to 100 so we declared an array of 101 vectors as indexing// starts from 0.vector<int> capList[101];Ā
// dp[2^10][101] .. in dp[i][j], i denotes the mask i.e., it tells that// how many and which persons are wearing cap. j denotes the first j caps// used. So, dp[i][j] tells the number ways we assign j caps to mask i// such that none of them wears the same capint dp[1025][101];Ā
// This is used for base case, it has all the N bits set// so, it tells whether all N persons are wearing a cap.int allmask;Ā
// Mask is the set of persons, i is cap-id (OR the // number of caps processed starting from first cap).long long int countWaysUtil(int mask, int i){Ā Ā Ā Ā // If all persons are wearing a cap so weĀ Ā Ā Ā // are done and this is one way so return 1Ā Ā Ā Ā if (mask == allmask) return 1;Ā
Ā Ā Ā Ā // If not everyone is wearing a cap and also there are no moreĀ Ā Ā Ā // caps left to process, so there is no way, thus return 0;Ā Ā Ā Ā if (i > 100) return 0;Ā
Ā Ā Ā Ā // If we already have solved this subproblem, return the answer.Ā Ā Ā Ā if (dp[mask][i] != -1) return dp[mask][i];Ā
Ā Ā Ā Ā // Ways, when we don't include this cap in our arrangementĀ Ā Ā Ā // or solution set.Ā Ā Ā Ā long long int ways = countWaysUtil(mask, i+1);Ā
Ā Ā Ā Ā // size is the total number of persons having cap with id i.Ā Ā Ā Ā int size = capList[i].size();Ā
Ā Ā Ā Ā // So, assign one by one ith cap to all the possible personsĀ Ā Ā Ā // and recur for remaining caps.Ā Ā Ā Ā for (int j = 0; j < size; j++)Ā Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā // if person capList[i][j] is already wearing a cap so continue asĀ Ā Ā Ā Ā Ā Ā Ā // we cannot assign him this capĀ Ā Ā Ā Ā Ā Ā Ā if (mask & (1 << capList[i][j])) continue;Ā
Ā Ā Ā Ā Ā Ā Ā Ā // Else assign him this cap and recur for remaining caps withĀ Ā Ā Ā Ā Ā Ā Ā // new updated mask vectorĀ Ā Ā Ā Ā Ā Ā Ā else ways += countWaysUtil(mask | (1 << capList[i][j]), i+1);Ā Ā Ā Ā Ā Ā Ā Ā ways %= MOD;Ā Ā Ā Ā }Ā
Ā Ā Ā Ā // Save the result and return it.Ā Ā Ā Ā return dp[mask][i] = ways;}Ā
// Reads n lines from standard input for current test casevoid countWays(int n){Ā Ā Ā Ā //----------- READ INPUT --------------------------Ā Ā Ā Ā string temp, str;Ā Ā Ā Ā int x;Ā Ā Ā Ā getline(cin, str);Ā // to get rid of newline characterĀ Ā Ā Ā for (int i=0; i<n; i++)Ā Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā getline(cin, str);Ā Ā Ā Ā Ā Ā Ā Ā stringstream ss(str);Ā
Ā Ā Ā Ā Ā Ā Ā Ā // while there are words in the streamobject ssĀ Ā Ā Ā Ā Ā Ā Ā while (ss >> temp)Ā Ā Ā Ā Ā Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā stringstream s;Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā s << temp;Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā s >> x;Ā
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // add the ith person in the list of cap if with id xĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā capList[x].push_back(i);Ā Ā Ā Ā Ā Ā Ā Ā }Ā Ā Ā Ā }Ā Ā Ā Ā //----------------------------------------------------Ā
Ā Ā Ā Ā // All mask is used to check whether all personsĀ Ā Ā Ā // are included or not, set all n bits as 1Ā Ā Ā Ā allmask = (1 << n) - 1;Ā
Ā Ā Ā Ā // Initialize all entries in dp as -1Ā Ā Ā Ā memset(dp, -1, sizeof dp);Ā
Ā Ā Ā Ā // Call recursive function count waysĀ Ā Ā Ā cout << countWaysUtil(0, 1) << endl;}Ā
// Driver Programint main(){ Ā Ā Ā Ā Ā int n;Ā Ā // number of persons in every test caseĀ Ā Ā Ā Ā cin >> n;Ā Ā Ā Ā Ā countWays(n);Ā Ā Ā Ā Ā return 0;} |
Java
// Java program to find number of ways to wear hatsĀ
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.Vector;Ā
class Test{Ā Ā Ā Ā static final int MOD = 1000000007;Ā Ā Ā Ā Ā Ā Ā Ā Ā // for inputĀ Ā Ā Ā static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));Ā Ā Ā Ā Ā Ā Ā Ā Ā // capList[i]'th vector contains the list of persons having a cap with id iĀ Ā Ā Ā // id is between 1 to 100 so we declared an array of 101 vectors as indexingĀ Ā Ā Ā // starts from 0.Ā Ā Ā Ā static Vector<Integer> capList[] = new Vector[101];Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // dp[2^10][101] .. in dp[i][j], i denotes the mask i.e., it tells thatĀ Ā Ā Ā // how many and which persons are wearing cap. j denotes the first j capsĀ Ā Ā Ā // used. So, dp[i][j] tells the number ways we assign j caps to mask iĀ Ā Ā Ā // such that none of them wears the same capĀ Ā Ā Ā static int dp[][] = new int[1025][101];Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // This is used for base case, it has all the N bits setĀ Ā Ā Ā // so, it tells whether all N persons are wearing a cap.Ā Ā Ā Ā static int allmask;Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Mask is the set of persons, i is cap-id (OR the Ā Ā Ā Ā // number of caps processed starting from first cap).Ā Ā Ā Ā static long countWaysUtil(int mask, int i)Ā Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā // If all persons are wearing a cap so weĀ Ā Ā Ā Ā Ā Ā Ā // are done and this is one way so return 1Ā Ā Ā Ā Ā Ā Ā Ā if (mask == allmask) return 1;Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // If not everyone is wearing a cap and also there are no moreĀ Ā Ā Ā Ā Ā Ā Ā // caps left to process, so there is no way, thus return 0;Ā Ā Ā Ā Ā Ā Ā Ā if (i > 100) return 0;Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // If we already have solved this subproblem, return the answer.Ā Ā Ā Ā Ā Ā Ā Ā if (dp[mask][i] != -1) return dp[mask][i];Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Ways, when we don't include this cap in our arrangementĀ Ā Ā Ā Ā Ā Ā Ā // or solution set.Ā Ā Ā Ā Ā Ā Ā Ā long ways = countWaysUtil(mask, i+1);Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // size is the total number of persons having cap with id i.Ā Ā Ā Ā Ā Ā Ā Ā int size = capList[i].size();Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // So, assign one by one ith cap to all the possible personsĀ Ā Ā Ā Ā Ā Ā Ā // and recur for remaining caps.Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < size; j++)Ā Ā Ā Ā Ā Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // if person capList[i][j] is already wearing a cap so continue asĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // we cannot assign him this capĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if ((mask & (1 << capList[i].get(j))) != 0) continue;Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Else assign him this cap and recur for remaining caps withĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // new updated mask vectorĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā else ways += countWaysUtil(mask | (1 << capList[i].get(j)), i+1);Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā ways %= MOD;Ā Ā Ā Ā Ā Ā Ā Ā }Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Save the result and return it.Ā Ā Ā Ā Ā Ā Ā Ā return dp[mask][i] = (int) ways;Ā Ā Ā Ā }Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Reads n lines from standard input for current test caseĀ Ā Ā Ā static void countWays(int n) throws ExceptionĀ Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā //----------- READ INPUT --------------------------Ā Ā Ā Ā Ā Ā Ā Ā String str;Ā Ā Ā Ā Ā Ā Ā Ā String split[];Ā Ā Ā Ā Ā Ā Ā Ā int x;Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for (int i=0; i<n; i++)Ā Ā Ā Ā Ā Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā str = br.readLine();Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā split = str.split(" ");Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // while there are words in the split[]Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < split.length; j++) {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // add the ith person in the list of cap if with id xĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā x = Integer.parseInt(split[j]);Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā capList[x].add(i);Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }Ā Ā Ā Ā Ā Ā Ā Ā //----------------------------------------------------Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // All mask is used to check of all personsĀ Ā Ā Ā Ā Ā Ā Ā // are included or not, set all n bits as 1Ā Ā Ā Ā Ā Ā Ā Ā allmask = (1 << n) - 1;Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Initialize all entries in dp as -1Ā Ā Ā Ā Ā Ā Ā Ā for (int[] is : dp) {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < is.length; i++) {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā is[i] = -1;Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }Ā Ā Ā Ā Ā Ā Ā Ā }Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Call recursive function count waysĀ Ā Ā Ā Ā Ā Ā Ā System.out.println(countWaysUtil(0, 1));Ā Ā Ā Ā }Ā
Ā Ā Ā Ā // Driver methodĀ Ā Ā Ā public static void main(String args[]) throws ExceptionĀ Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā int n;Ā Ā // number of persons in every test caseĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // initializing vector arrayĀ Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < capList.length; i++)Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā capList[i] = new Vector<>();Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā n = Integer.parseInt(br.readLine());Ā Ā Ā Ā Ā Ā Ā Ā countWays(n);Ā Ā Ā Ā }}// This code is contributed by Gaurav Miglani |
Python
#Python program to find number of ways to wear hatsfrom collections import defaultdictĀ
class AssignCap:Ā
Ā Ā Ā Ā # Initialize variablesĀ Ā Ā Ā def __init__(self):Ā
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā self.allmask = 0Ā
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā self.total_caps = 100Ā
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā self.caps = defaultdict(list)Ā
Ā
Ā Ā Ā Ā #Ā Mask is the set of persons, i is the current cap number.Ā Ā Ā Ā def countWaysUtil(self,dp, mask, cap_no):Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā # If all persons are wearing a cap so weĀ Ā Ā Ā Ā Ā Ā Ā # are done and this is one way so return 1Ā Ā Ā Ā Ā Ā Ā Ā if mask == self.allmask:Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return 1Ā
Ā Ā Ā Ā Ā Ā Ā Ā # If not everyone is wearing a cap and also there are no moreĀ Ā Ā Ā Ā Ā Ā Ā # caps left to process, so there is no way, thus return 0;Ā Ā Ā Ā Ā Ā Ā Ā if cap_no > self.total_caps:Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return 0Ā
Ā Ā Ā Ā Ā Ā Ā Ā # If we have already solved this subproblem, return the answer.Ā Ā Ā Ā Ā Ā Ā Ā if dp[mask][cap_no]!= -1 :Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return dp[mask][cap_no]Ā
Ā Ā Ā Ā Ā Ā Ā Ā # Ways, when we don't include this cap in our arrangementĀ Ā Ā Ā Ā Ā Ā Ā # or solution setĀ Ā Ā Ā Ā Ā Ā Ā ways = self.countWaysUtil(dp, mask, cap_no + 1)Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā # assign ith cap one by oneĀ to all the possible personsĀ Ā Ā Ā Ā Ā Ā Ā # and recur for remaining caps.Ā Ā Ā Ā Ā Ā Ā Ā if cap_no in self.caps:Ā
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for ppl in self.caps[cap_no]:Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā # if person 'ppl' is already wearing a cap then continueĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if mask & (1 << ppl) : continueĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā # Else assign him this cap and recur for remaining caps withĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā # new updated mask vectorĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā ways += self.countWaysUtil(dp, mask | (1 << ppl), cap_no + 1) Ā
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā ways = ways % (10**9 + 7)Ā
Ā Ā Ā Ā Ā Ā Ā Ā # Save the result and return itĀ Ā Ā Ā Ā Ā Ā Ā dp[mask][cap_no] = waysĀ
Ā Ā Ā Ā Ā Ā Ā Ā return dp[mask][cap_no]Ā
Ā
Ā
Ā Ā Ā Ā def countWays(self,N):Ā
Ā Ā Ā Ā Ā Ā Ā Ā # Reads n lines from standard input for current test caseĀ Ā Ā Ā Ā Ā Ā Ā # create dictionary for cap. cap[i] = list of person havingĀ Ā Ā Ā Ā Ā Ā Ā # cap no iĀ Ā Ā Ā Ā Ā Ā Ā for ppl in range(N):Ā
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā cap_possessed_by_person = map(int, raw_input().strip().split())Ā
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for i in cap_possessed_by_person:Ā
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā self.caps[i].append(ppl)Ā
Ā Ā Ā Ā Ā Ā Ā Ā # allmask is used to check if all personsĀ Ā Ā Ā Ā Ā Ā Ā # are included or not, set all n bits as 1Ā Ā Ā Ā Ā Ā Ā Ā self.allmask = (1 << N) -1Ā
Ā Ā Ā Ā Ā Ā Ā Ā # Initialize all entries in dp as -1Ā Ā Ā Ā Ā Ā Ā Ā dp = [[-1 for j in range(self.total_caps + 1)] for i in range(2 ** N)]Ā
Ā Ā Ā Ā Ā Ā Ā Ā # Call recursive function countWaysUtilĀ Ā Ā Ā Ā Ā Ā Ā # result will be in dp[0][1]Ā Ā Ā Ā Ā Ā Ā Ā print self.countWaysUtil(dp, 0, 1,)Ā
#Driver Programdef main():Ā Ā Ā Ā No_of_people = input() # number of persons in every test caseĀ
Ā Ā Ā Ā AssignCap().countWays(No_of_people)Ā
Ā
if __name__ == '__main__':Ā Ā Ā Ā main()Ā
# This code is contributed by Neelam Yadav |
C#
using System;using System.Collections.Generic;using System.IO;Ā
class Test {Ā Ā Ā Ā const int MOD = 1000000007;Ā Ā Ā Ā // for inputĀ Ā Ā Ā static StreamReader brĀ Ā Ā Ā Ā Ā Ā Ā = new StreamReader(Console.OpenStandardInput());Ā
Ā Ā Ā Ā // capList[i]'th vector contains the list of personsĀ Ā Ā Ā // having a cap with id i id is between 1 to 100 so weĀ Ā Ā Ā // declared an array of 101 vectors as indexing startsĀ Ā Ā Ā // from 0.Ā Ā Ā Ā static List<int>[] capList = new List<int>[ 101 ];Ā Ā Ā Ā // dp[2^10][101] .. in dp[i][j], i denotes the maskĀ Ā Ā Ā // i.e., it tells that how many and which persons areĀ Ā Ā Ā // wearing cap. j denotes the first j caps used. So,Ā Ā Ā Ā // dp[i][j] tells the number ways we assign j caps toĀ Ā Ā Ā // mask i such that none of them wears the same capĀ Ā Ā Ā static int[, ] dp = new int[1025, 101];Ā
Ā Ā Ā Ā // This is used for base case, it has all the N bits setĀ Ā Ā Ā // so, it tells whether all N persons are wearing a cap.Ā Ā Ā Ā static int allmask;Ā
Ā Ā Ā Ā // Mask is the set of persons, i is cap-id (OR theĀ Ā Ā Ā // number of caps processed starting from first cap).Ā Ā Ā Ā static long countWaysUtil(int mask, int i)Ā Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā // If all persons are wearing a cap so weĀ Ā Ā Ā Ā Ā Ā Ā // are done and this is one way so return 1Ā Ā Ā Ā Ā Ā Ā Ā if (mask == allmask)Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return 1;Ā
Ā Ā Ā Ā Ā Ā Ā Ā // If not everyone is wearing a cap and also thereĀ Ā Ā Ā Ā Ā Ā Ā // are no more caps left to process, so there is noĀ Ā Ā Ā Ā Ā Ā Ā // way, thus return 0;Ā Ā Ā Ā Ā Ā Ā Ā if (i > 100)Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return 0;Ā
Ā Ā Ā Ā Ā Ā Ā Ā // If we already have solved this subproblem, returnĀ Ā Ā Ā Ā Ā Ā Ā // the answer.Ā Ā Ā Ā Ā Ā Ā Ā if (dp[mask, i] != -1)Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return dp[mask, i];Ā
Ā Ā Ā Ā Ā Ā Ā Ā // Ways, when we don't include this cap in ourĀ Ā Ā Ā Ā Ā Ā Ā // arrangement or solution set.Ā Ā Ā Ā Ā Ā Ā Ā long ways = countWaysUtil(mask, i + 1);Ā
Ā Ā Ā Ā Ā Ā Ā Ā // size is the total number of persons having capĀ Ā Ā Ā Ā Ā Ā Ā // with id i.Ā Ā Ā Ā Ā Ā Ā Ā int size = capList[i].Count;Ā
Ā Ā Ā Ā Ā Ā Ā Ā // So, assign one by one ith cap to all the possibleĀ Ā Ā Ā Ā Ā Ā Ā // personsĀ Ā Ā Ā Ā Ā Ā Ā // and recur for remaining caps.Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < size; j++) {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // if person capList[i][j] is already wearing aĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // cap so continue asĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // we cannot assign him this capĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if ((mask & (1 << capList[i][j])) != 0)Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā continue;Ā
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // Else assign him this cap and recur forĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // remaining caps withĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // new updated mask vectorĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā elseĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā ways += countWaysUtil(Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā mask | (1 << capList[i][j]), i + 1);Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā ways %= MOD;Ā Ā Ā Ā Ā Ā Ā Ā }Ā Ā Ā Ā Ā Ā Ā Ā // Save the result and return it.Ā Ā Ā Ā Ā Ā Ā Ā return dp[mask, i] = (int)ways;Ā Ā Ā Ā }Ā
Ā Ā Ā Ā // Reads n lines from standard input for current testĀ Ā Ā Ā // caseĀ Ā Ā Ā static void countWays(int n)Ā Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā //----------- READ INPUT --------------------------Ā Ā Ā Ā Ā Ā Ā Ā string str;Ā Ā Ā Ā Ā Ā Ā Ā string[] split;Ā Ā Ā Ā Ā Ā Ā Ā int x;Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā str = br.ReadLine();Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā split = str.Split(' ');Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // while there are words in the split[]Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < split.Length; j++) {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // add the ith person in the list of cap ifĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā // with id xĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā x = int.Parse(split[j]);Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā capList[x].Add(i);Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }Ā Ā Ā Ā Ā Ā Ā Ā }Ā
Ā Ā Ā Ā Ā Ā Ā Ā //----------------------------------------------------Ā
Ā Ā Ā Ā Ā Ā Ā Ā // All mask is used to check of all personsĀ Ā Ā Ā Ā Ā Ā Ā // are included or not, set all n bits as 1Ā Ā Ā Ā Ā Ā Ā Ā allmask = (1 << n) - 1;Ā
Ā Ā Ā Ā Ā Ā Ā Ā // Initialize all entries in dp as -1Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < dp.GetLength(0); i++) {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < dp.GetLength(1); j++) {Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dp[i, j] = -1;Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }Ā Ā Ā Ā Ā Ā Ā Ā }Ā Ā Ā Ā Ā Ā Ā Ā // Call recursive function count waysĀ Ā Ā Ā Ā Ā Ā Ā Console.WriteLine(countWaysUtil(0, 1));Ā Ā Ā Ā }Ā
Ā Ā Ā Ā // Driver methodĀ Ā Ā Ā public static void Main()Ā Ā Ā Ā {Ā Ā Ā Ā Ā Ā Ā Ā int n; // number of persons in every test caseĀ
Ā Ā Ā Ā Ā Ā Ā Ā // initializing vector arrayĀ Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < capList.Length; i++)Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā capList[i] = new List<int>();Ā
Ā Ā Ā Ā Ā Ā Ā Ā n = int.Parse(br.ReadLine());Ā Ā Ā Ā Ā Ā Ā Ā countWays(n);Ā Ā Ā Ā }} |
Input:
3 5 100 1 2 5 100
Output:
4
Time Complexity: O(n*2^n), where n is the number of persons. This is because the recursive function is called at most 2^n times and the for loop is executed at most n times.
Auxiliary Space: O(n*2^n), as we are using a dp 2D array of size n*2^n.
This article is contributed by Gaurav Ahirwar. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

[…] Bitmasking and Dynamic Programming | Set 1 […]
[…] Efficient Approach: The above problem can be solved using bitmask DP.Ā Ā […]