Bitmasking for DP (revisited) šŸŽÆ

beginner
6 min

Bitmasking for DP (revisited) šŸŽÆ

Welcome back to CodeYourCraft! Today, we're diving deep into the fascinating world of Bitmasking. It's a powerful technique that can help solve complex problems more efficiently, especially when it comes to Dynamic Programming (DP). Let's dive in! šŸ’”

What is Bitmasking? šŸ“

Bitmasking is a technique used in computer programming to represent sets or multiple flags within a single integer. It leverages the binary representation of numbers to achieve this.

Binary Representation šŸ“

Every number has a binary representation. For example, the decimal number 5 in binary is 101.

markdown
Decimal: 5 Binary: 101

In binary, each digit (0 or 1) is called a bit. The nth bit from the right represents 2^(n-1).

Bitmasking in DP šŸ“

Bitmasking can be a game-changer in Dynamic Programming (DP). It helps in handling multiple cases or states efficiently. Let's see an example.

Example: Knapsack Problem šŸ“

The classic Knapsack problem is about choosing a subset of items to put in a knapsack such that the total weight does not exceed a certain limit and the maximum value is obtained.

Code Example šŸ’» (C++ version)

cpp
#include <iostream> #include <vector> #include <climits> using namespace std; const int MAX_WEIGHT = 100; int dp[MAX_WEIGHT + 1]; void knapSack(int wt[], int val[], int w, int n) { for (int i = 0; i <= w; i++) { for (int j = 1; j <= n; j++) { if (i >= wt[j]) dp[i] = max(dp[i], dp[i - wt[j]] + val[j]); } } } int main() { int val[] = {60, 100, 120}; int wt[] = {10, 20, 30}; int w = 50, n = 3; knapSack(wt, val, w, n); cout << "The maximum value that can be obtained is: " << dp[w] << endl; return 0; }

In the above example, we are using two nested loops to calculate the maximum value for each weight capacity i. This approach might not seem inefficient, but as the number of items (n) and weights (wt) grow, the number of iterations increases exponentially.

Bitmasking to the Rescue šŸ’»

Let's rewrite the above code using bitmasking. In this example, we'll consider that every item can be picked (1) or not picked (0). We'll use a single integer mask to represent all the items.

cpp
#include <iostream> #include <vector> #include <climits> using namespace std; const int MAX_WEIGHT = 100; int dp[MAX_WEIGHT + 1]; void knapSack(int wt[], int val[], int w, int n) { for (int i = 1; i <= (1 << n); i++) { for (int j = 1; j <= n; j++) { if (i & (1 << (n - j))) { if (wt[j] > w) break; dp[w] = max(dp[w], dp[w - wt[j]] + val[j]); } } dp[w] = max(dp[w], dp[w]); w--; } } int main() { int val[] = {60, 100, 120}; int wt[] = {10, 20, 30}; int w = 50, n = 3; knapSack(wt, val, w, n); cout << "The maximum value that can be obtained is: " << dp[w] << endl; return 0; }

In the bitmasking version, we use a single loop to iterate through all possible combinations of items. The line if (i & (1 << (n - j))) checks if the jth item is included in the current combination.

With bitmasking, the time complexity is reduced from O(2^n) to O(n2). That's a significant improvement for larger problems.

Bitmasking Techniques šŸ“

There are several bitmasking techniques that you can learn to solve various problems more efficiently. Some of them are:

  1. Checking Bit: Checking if a specific bit is set or not
  2. Setting Bit: Setting a specific bit to 1
  3. Clearing Bit: Setting a specific bit to 0
  4. Toggling Bit: Toggling the state of a specific bit
  5. Flipping Bits: Setting all bits to 1 or 0

Quiz šŸŽ“

Quick Quiz
Question 1 of 1

Which of the following represents the binary representation of decimal number `13`?


That's it for today! Bitmasking is a powerful tool in a programmer's arsenal. Understanding it will help you solve complex problems more efficiently. Stay tuned for more tutorials on advanced techniques and practical examples. Happy learning! šŸ¤“