from functools import lru_cache
class Solution:
def connectTwoGroups(self, cost):
m, n = len(cost), len(cost[0])
@lru_cache(None)
def dp(i, mask):
if i == m:
# All group1 done, connect any unconnected group2
res = 0
for j in range(n):
if not (mask & (1 << j)):
res += min(cost[k][j] for k in range(m))
return res
res = float('inf')
for j in range(n):
res = min(res, cost[i][j] + dp(i+1, mask | (1 << j)))
return res
return dp(0, 0)
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
class Solution {
public:
int connectTwoGroups(vector<vector<int>>& cost) {
int m = cost.size(), n = cost[0].size();
int MAX = 1 << n;
vector<vector<int>> dp(m+1, vector<int>(MAX, INT_MAX/2));
dp[0][0] = 0;
for (int i = 0; i < m; ++i) {
for (int mask = 0; mask < MAX; ++mask) {
if (dp[i][mask] >= INT_MAX/2) continue;
for (int j = 0; j < n; ++j) {
int new_mask = mask | (1 << j);
dp[i+1][new_mask] = min(dp[i+1][new_mask], dp[i][mask] + cost[i][j]);
}
}
}
int res = INT_MAX;
for (int mask = 0; mask < MAX; ++mask) {
int val = dp[m][mask];
for (int j = 0; j < n; ++j) {
if (!(mask & (1 << j))) {
int minc = INT_MAX;
for (int i = 0; i < m; ++i)
minc = min(minc, cost[i][j]);
val += minc;
}
}
res = min(res, val);
}
return res;
}
};
import java.util.*;
class Solution {
public int connectTwoGroups(List<List<Integer>> cost) {
int m = cost.size(), n = cost.get(0).size();
int MAX = 1 << n;
int[][] dp = new int[m+1][MAX];
for (int[] row : dp) Arrays.fill(row, Integer.MAX_VALUE / 2);
dp[0][0] = 0;
for (int i = 0; i < m; ++i) {
for (int mask = 0; mask < MAX; ++mask) {
if (dp[i][mask] >= Integer.MAX_VALUE / 2) continue;
for (int j = 0; j < n; ++j) {
int new_mask = mask | (1 << j);
dp[i+1][new_mask] = Math.min(dp[i+1][new_mask], dp[i][mask] + cost.get(i).get(j));
}
}
}
int res = Integer.MAX_VALUE;
for (int mask = 0; mask < MAX; ++mask) {
int val = dp[m][mask];
for (int j = 0; j < n; ++j) {
if ((mask & (1 << j)) == 0) {
int minc = Integer.MAX_VALUE;
for (int i = 0; i < m; ++i)
minc = Math.min(minc, cost.get(i).get(j));
val += minc;
}
}
res = Math.min(res, val);
}
return res;
}
}
var connectTwoGroups = function(cost) {
const m = cost.length, n = cost[0].length;
const MAX = 1 << n;
const dp = Array.from({length: m+1}, () => Array(MAX).fill(Infinity));
dp[0][0] = 0;
for (let i = 0; i < m; ++i) {
for (let mask = 0; mask < MAX; ++mask) {
if (dp[i][mask] === Infinity) continue;
for (let j = 0; j < n; ++j) {
let new_mask = mask | (1 << j);
dp[i+1][new_mask] = Math.min(dp[i+1][new_mask], dp[i][mask] + cost[i][j]);
}
}
}
let res = Infinity;
for (let mask = 0; mask < MAX; ++mask) {
let val = dp[m][mask];
for (let j = 0; j < n; ++j) {
if ((mask & (1 << j)) === 0) {
let minc = Infinity;
for (let i = 0; i < m; ++i)
minc = Math.min(minc, cost[i][j]);
val += minc;
}
}
res = Math.min(res, val);
}
return res;
};
group1 and group2, and a cost matrix cost where cost[i][j] is the cost of connecting the i-th point in group1 to the j-th point in group2, your task is to connect every point in both groups such that:
group1 is connected to at least one point in group2.group2 is connected to at least one point in group1.
The input is a 2D integer array cost of size m x n where m and n are the sizes of group1 and group2 respectively.
group2 have been connected so far, and use dynamic programming to avoid redundant calculations.
i be the index of the current point in group1 we are processing.mask be a bitmask representing which points in group2 have already been connected.i in group1, try connecting it to every point j in group2.mask to include j and recursively process the next point in group1.group1 have been processed (i == m), check if there are any points in group2 not yet connected (i.e., bits in mask are 0).group2, connect it to the cheapest point in group1 (choose the minimum cost in its column).(i, mask) pair to avoid redundant calculations.i = 0 and mask = 0 (no points in group2 connected yet).
This approach is justified because the number of possible masks is at most 2^n (where n is up to 12), making it feasible for dynamic programming.
Suppose cost = [[1,3,5],[4,1,1],[1,5,3]].
Here, group1 has 3 points, group2 has 3 points.
group1 (i=0), try connecting to each point in group2 (j=0,1,2):
group1 (i=1), and repeat, updating the mask each time.
group1 are processed (i=3).
group2 are covered. If not, connect the remaining ones at minimum additional cost.
The optimal solution for this input is 4 (connect 0->0, 1->1, 2->2).
n^m (exponential and infeasible for large n,m).m possible indices for group1 and 2^n possible masks for group2.O(n) time (for each possible connection).O(m * n * 2^n).O(m * 2^n) for memoization.n <= 12 as in Leetcode constraints.
The problem of finding the minimum cost to connect two groups of points is solved efficiently using dynamic programming with bitmasking. By representing the state as which points in group2 have been connected and building up the solution incrementally, we avoid redundant work and ensure all constraints are met. The key insight is to use bitmask DP to cover all points while minimizing cost, making the approach both elegant and practical for small group sizes.