Open in App
Not now

Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique cap to every person)

• Difficulty Level : Hard
• Last Updated : 18 Jan, 2023

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)```

```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

// 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` `#define MOD 1000000007` `using` `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 cap` `int` `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 case` `void` `countWays(``int` `n)` `{` `    ``//----------- READ INPUT --------------------------` `    ``string temp, str;` `    ``int` `x;` `    ``getline(cin, str);  ``// to get rid of newline character` `    ``for` `(``int` `i=0; i> 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 Program` `int` `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 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 = Integer.parseInt(br.readLine());` `        ``countWays(n);` `    ``}` `}` `// This code is contributed by Gaurav Miglani`

Python

 `#Python program to find number of ways to wear hats` `from` `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 Program` `def` `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`

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.