Description Link to heading

1595. Minimum Cost to Connect Two Groups of Points (Hard)

Solution Link to heading

Dynamic Programming + State Compression

We use a binary number $j$ to represent the set of chosen elements from the second group. $dp[i][j]$ denotes the minimum cost of connecting the first $i$ elements from the first group and the set of elements $j$ from the second group.

To establish the recurrence relation, we consider the elements from the first group. Let’s focus on the $i$-th element and iterate through the elements $k$ in the set (where $k$ represents the element index). We encounter the following scenarios:

  • The $i$-th element is only connected to $k$. In this case, we have two possibilities:
    • The element in the second group with index $k$ is solely connected to the $i$-th element: $dp[i][j] = \min(dp[i][j], dp[i - 1][j\oplus(1 « k)] + \text{cost}[i - 1][k])$.
    • The element in the second group with index $k$ is connected to other elements as well: $dp[i][j] = \min(dp[i][j], dp[i - 1][j] + \text{cost}[i - 1][k])$.
  • The $i$-th element is connected to elements other than $k$. In this case, we also have two possibilities:
    • The element in the second group with index $k$ is solely connected to the $i$-th element: $dp[i][j] = \min(dp[i][j], dp[i][j\oplus (1 « k)] + \text{cost}[i - 1][k])$.
    • The element in the second group with index $k$ is connected to other elements besides the $i$-th element. At this point, the $i$-th element does not need to be connected to the element with index $k$ anymore. Thus, we can eliminate the unnecessary edge. If we forcibly connect the $i$-th element and element $k$, redundant edges will be introduced. Therefore, we consider the aforementioned three cases by enumerating $k_1$, $k$, or $k_2$.

Please note that each time we iterate through $k$, we need to compare it with the previously calculated $dp[i][j]$! Additionally, if the condition in the for loop is not satisfied, the loop will terminate.

Code Link to heading

class Solution {
  public:
    int connectTwoGroups(vector<vector<int>> &cost) {
        int m = cost.size(), n = cost[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(1 << n, INT_MAX));
        dp[0][0] = 0;
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j < (1 << n); ++j) {
                for (int k = 0; (1 << k) <= j; ++k) {
                    if (((1 << k) & j) == 0) {
                        continue;
                    }
                    int tmp = min(dp[i][j ^ (1 << k)], min(dp[i - 1][j ^ (1 << k)], dp[i - 1][j])) + cost[i - 1][k];
                    dp[i][j] = min(tmp, dp[i][j]);
                }
            }
        }
        return dp[m][(1 << n) - 1];
    }
};