Not Frequent
 0/22

Bitmask DP

Authors: Michael Cao, Siyong Huang, Peng Bai

Contributors: Andrew Wang, Neo Wang

DP problems that require iterating over subsets.

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 dp[S][i]dp[S][i] be the number of routes that visit all the cities in the subset SS and end at city ii. The transitions will then be:

dp[S][i]=xadj[i]dp[S{i}][x] if xSdp[S][i] = \sum_{x \in adj[i]} dp[S \setminus \{i\}][x] \text{ if $x \in S$}

where S{i}S \setminus \{i\} is the subset SS without city ii.

Time Complexity: O(2NN2)\mathcal{O}(2^N \cdot N^2)

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 sys
MOD = 10**9 + 7
input = sys.stdin.readline
n, 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 SS, it is not sufficient to transition from S{i}S \setminus \{i\}. Instead, it is necessary to transition from all strict subsets of SS.

Though it may seem like we have to do O(2N2N)=O(4N)\mathcal{O}(2^N \cdot 2^N) = \mathcal{O}(4^N) transitions, theres really only O(3N)\mathcal{O}(3^N) transitions!

To see why, let's count the number of ordered pairs (T,S)(T, S) where TST \subset S. Instead of counting directly, notice that each element xx is either:

  1. In TT and SS
  2. In neither
  3. In SS but not in TT.

If xx is in TT but not in SS, TT isn't a valid subset.

Given that each element can be in three possible states, our overall complexity is actually O(3N)\mathcal{O}(3^N).

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 11 from submask\texttt{submask}, the rightmost bit flips to a 00 and all bits to the right of it will become 11. Applying the bitwise AND with mask\texttt{mask} removes all extra bits not in mask\texttt{mask}. From this process, we can get all strict subsets in increasing order by calculating masksubmask\texttt{mask} \oplus \texttt{submask}, 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 dp[S]\texttt{dp}[S] be the minimum number of partitions such that in each partition, the graph formed is a complete graph.

We can first find which sets TT form a complete graph, setting dp[T]\texttt{dp}[T] to 11 and \infty otherwise. This can be done naively in O(2NN2)\mathcal{O}(2^N \cdot N^2) or O(2NN)\mathcal{O}(2^N \cdot N) 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:

dp[S]=minTS(dp[T]+dp[ST])\texttt{dp}[S] = \min_{T \subset S} (\texttt{dp}[T] + \texttt{dp}[S \setminus T])

Implementation

Time Complexity: O(3N+2NN)\mathcal{O}(3^N + 2^N \cdot N)

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

StatusSourceProblem NameDifficultyTags
ACEasy
Show TagsBitmasks, DP
ACEasy
Show TagsBitmasks, DP
CFEasy
Show TagsBitmasks, MinCostFlow
Old GoldEasy
Show TagsBitmasks, DP
Old GoldEasy
Show TagsBitmasks, DP
GoldNormal
Show TagsBitmasks, DP
CSESNormal
Show TagsBitmasks, DP
IZhONormal
Show TagsBitmasks, DP
KattisNormal
Show TagsBinary Search, Bitmasks, DP, Geometry
YSHard
Show TagsBitmasks, DP, Meet in Middle
GoldHard
Show TagsBitwise, DP
IZhOHard
Show TagsBitmasks, DP
COCIHard
Show TagsBitmasks, DP, Game Theory, Tree
GoldHard
Show TagsBitmasks, DP
CEOIVery Hard
Show TagsBitmasks, DP
IOIVery 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 {6,10,15}\{6, 10, 15 \} can be represented by {0b011,0b101,0b110}\{0b011, 0b101, 0b110 \} (in binary), where the bits correspond to divisibility by [2,3,5][2, 3, 5].

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 11 is equivalent to choosing a set of bitmasks that AND to 00. For example, we can see that {6,10}\{6, 10 \} doesn't have GCD 11 because 0b011&0b101=0b00100b011 \& 0b101 = 0b001 \neq 0. On the other hand, {6,10,15}\{6, 10, 15 \} has GCD 11 because 0b011&0b101&0b110=0b000=00b011 \& 0b101 \& 0b110 = 0b000 = 0.

Problems

StatusSourceProblem NameDifficultyTags
CFHard
Show TagsCombinatorics, DP
CFVery Hard
Show TagsBitmasks, DP, NT
CFInsane
Show TagsBinary Search, Bitmasks, NT
CFInsane
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!