Pro Tip
You can often use this to solve subtasks.
Bitmask DP
Focus Problem – try your best to solve this problem before continuing!
Tutorial
| Resources | |||||
|---|---|---|---|---|---|
| CPH | Elevator Rides, SOS, Hamiltonian | ||||
| nwatx | |||||
| PAPS | example - similar to Hamiltonian | ||||
| CF | Hamiltonian walks | ||||
| DPCC | Diagram | ||||
| HE | |||||
Solution
Let be the number of routes that visit all the cities in the subset and end at city . The transitions will then be:
where is the subset without city .
Time Complexity:
C++
#include <bits/stdc++.h>using namespace std;using ll = long long;const int MAX_N = 20;const ll MOD = (ll)1e9 + 7;ll dp[1 << MAX_N][MAX_N];// come_from[i] contains the cities that can fly to i
Python
Warning!
Due to Python's large constant factor, the solution below TLEs.
import sysMOD = 10**9 + 7input = sys.stdin.readlinen, m = map(int, input().strip().split())dp = [[0 for _ in range(n)] for _ in range(1 << n)]dp[1][0] = 1
Merging Subsets
In some problems, for a set , it is not sufficient to transition from . Instead, it is necessary to transition from all strict subsets of .
Though it may seem like we have to do transitions, there's really only transitions!
To see why, let's count the number of ordered pairs where . Instead of counting directly, notice that each element is either:
- In and
- In neither
- In but not in .
If is in but not in , isn't a valid subset.
Given that each element can be in three possible states, our overall complexity is actually .
To implement this, we can do some bitwise tricks:
C++
for (int mask = 0; mask < (1 << n); mask++) {for (int submask = mask; submask != 0; submask = (submask - 1) & mask) {int subset = mask ^ submask;// do whatever you need to do here}}
When we subtract from , the rightmost bit flips to a and all bits to the right of it will become . Applying the bitwise AND with removes all extra bits not in . From this process, we can get all strict subsets in increasing order by calculating , which does set subtraction.
Focus Problem – try your best to solve this problem before continuing!
Explanation
The goal of this problem is to partition the nodes into sets such that the nodes in each set form a complete graph. Let be the minimum number of partitions such that in each partition, the graph formed is a complete graph.
We can first find which sets form a complete graph, setting to and otherwise. This can be done naively in or by setting the adjacency list as a bitmask and using bit manipulations if a set of nodes is a complete graph.
Then we can transition as follows:
Implementation
Time Complexity:
C++
#include <bits/stdc++.h>using namespace std;int main() {int n, m;cin >> n >> m;vector<int> adj(n);for (int i = 0; i < m; i++) {int u, v;cin >> u >> v;
Problems
| Status | Source | Problem Name | Difficulty | Tags | ||
|---|---|---|---|---|---|---|
| AC | Easy | Show TagsBitmasks, DP | ||||
| AC | Easy | Show TagsBitmasks, DP | ||||
| CF | Easy | Show TagsBitmasks, MinCostFlow | ||||
| Old Gold | Easy | Show TagsBitmasks, DP | ||||
| Old Gold | Easy | Show TagsBitmasks, DP | ||||
| Gold | Normal | Show TagsBitmasks, DP | ||||
| CSES | Normal | Show TagsBitmasks, DP | ||||
| IZhO | Normal | Show TagsBitmasks, DP | ||||
| Kattis | Normal | Show TagsBinary Search, Bitmasks, DP, Geometry | ||||
| Gold | Hard | Show TagsBitmasks, DP, Graphs | ||||
| YS | Hard | Show TagsBitmasks, DP, Meet in Middle | ||||
| Gold | Hard | Show TagsBitwise, DP | ||||
| IZhO | Hard | Show TagsBitmasks, DP | ||||
| Gold | Hard | Show TagsBitmasks, DP | ||||
| COCI | Very Hard | Show TagsBitmasks, DP, Game Theory, Tree | ||||
| CEOI | Very Hard | Show TagsBitmasks, DP | ||||
| IOI | Very Hard | Show TagsBitmasks, DFS, DP, Tree | ||||
Application - Bitmask over Primes
Rough Idea
In some number theory problems, it helps to represent each number with a bitmask of its prime divisors. For example, the set can be represented by (in binary), where the bits correspond to divisibility by .
Then, here are some equivalent operations between masks and these integers:
- Bitwise AND is GCD
- Bitwise OR is LCM
- Iterating over bits is iterating over prime divisors
- Iterating over submasks is iterating over divisors
Choosing a set with GCD is equivalent to choosing a set of bitmasks that AND to . For example, we can see that doesn't have GCD because . On the other hand, has GCD because .
Problems
| Status | Source | Problem Name | Difficulty | Tags | ||
|---|---|---|---|---|---|---|
| CF | Hard | Show TagsCombinatorics, DP | ||||
| CF | Very Hard | Show TagsBitmasks, DP, NT | ||||
| CF | Insane | Show TagsBinary Search, Bitmasks, NT | ||||
| CF | Insane | Show TagsBitmasks, Combinatorics, DP | ||||
Module Progress:
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!