Maximum Compatibility Score Sum

medium backtracking bitmask array

Problem

You are given two equal-sized lists of binary answer sheets: one row per student and one row per mentor, every row having the same number of yes/no answers. Pairing a student with a mentor scores one point for each question where their answers agree. Assign every student to a different mentor (a one-to-one matching) so the total agreement score across all pairs is as large as possible, and return that maximum total.

Inputstudents = [[1,1,0],[1,0,1],[0,0,1]], mentors = [[1,0,0],[0,0,1],[1,1,0]]
Output8
Assign student 0 → mentor 2 (score 3), student 1 → mentor 0 (score 2), student 2 → mentor 1 (score 3). Total = 3 + 2 + 3 = 8, the best possible.

def max_compatibility_sum(students, mentors):
    m, n = len(students), len(students[0])
    score = [[0] * m for _ in range(m)]
    for i in range(m):
        for j in range(m):
            score[i][j] = sum(students[i][q] == mentors[j][q] for q in range(n))

    best = [0]
    used = [False] * m

    def dfs(i, total):
        if i == m:
            best[0] = max(best[0], total)
            return
        for j in range(m):
            if not used[j]:
                used[j] = True
                dfs(i + 1, total + score[i][j])
                used[j] = False

    dfs(0, 0)
    return best[0]
function maxCompatibilitySum(students, mentors) {
  const m = students.length, n = students[0].length;
  const score = Array.from({ length: m }, () => new Array(m).fill(0));
  for (let i = 0; i < m; i++)
    for (let j = 0; j < m; j++)
      for (let q = 0; q < n; q++)
        if (students[i][q] === mentors[j][q]) score[i][j]++;

  let best = 0;
  const used = new Array(m).fill(false);
  function dfs(i, total) {
    if (i === m) { best = Math.max(best, total); return; }
    for (let j = 0; j < m; j++) {
      if (!used[j]) {
        used[j] = true;
        dfs(i + 1, total + score[i][j]);
        used[j] = false;
      }
    }
  }
  dfs(0, 0);
  return best;
}
class Solution {
    int best;
    public int maxCompatibilitySum(int[][] students, int[][] mentors) {
        int m = students.length, n = students[0].length;
        int[][] score = new int[m][m];
        for (int i = 0; i < m; i++)
            for (int j = 0; j < m; j++)
                for (int q = 0; q < n; q++)
                    if (students[i][q] == mentors[j][q]) score[i][j]++;
        best = 0;
        dfs(score, new boolean[m], 0, 0, m);
        return best;
    }
    void dfs(int[][] score, boolean[] used, int i, int total, int m) {
        if (i == m) { best = Math.max(best, total); return; }
        for (int j = 0; j < m; j++) {
            if (!used[j]) {
                used[j] = true;
                dfs(score, used, i + 1, total + score[i][j], m);
                used[j] = false;
            }
        }
    }
}
int best;
void dfs(vector<vector<int>>& score, vector<bool>& used, int i, int total, int m) {
    if (i == m) { best = max(best, total); return; }
    for (int j = 0; j < m; j++) {
        if (!used[j]) {
            used[j] = true;
            dfs(score, used, i + 1, total + score[i][j], m);
            used[j] = false;
        }
    }
}
int maxCompatibilitySum(vector<vector<int>>& students, vector<vector<int>>& mentors) {
    int m = students.size(), n = students[0].size();
    vector<vector<int>> score(m, vector<int>(m, 0));
    for (int i = 0; i < m; i++)
        for (int j = 0; j < m; j++)
            for (int q = 0; q < n; q++)
                if (students[i][q] == mentors[j][q]) score[i][j]++;
    best = 0;
    vector<bool> used(m, false);
    dfs(score, used, 0, 0, m);
    return best;
}
Time: O(m·m·n + m!) Space: O(m·m)