Open In App

Maximize count of indices with same element by pairing rows from given Matrices

Improve
Improve
Like Article
Like
Save
Share
Report

Given two 2D binary arrays, a[][] and b[][] both of size M*N, the task is to pair each row in the array a[][] with any row in the array b[][] such that the total score can be maximized and the score for each pair is calculated as the total indexes at which values of both rows are identical.

Note: Each row of the array b[][] can only be paired with a single row of vector a[][].

Examples:

Input: a[][] = {{1, 1, 0}, {1, 0, 1}, {0, 0, 1}}, b[][] = {{1, 0, 0}, {0, 0, 1}, {1, 1, 0}}
Output: 8
Explanation:
Consider the pairing of rows in the following order, to maximize the total score obtained:

  • Row 0 of a[][] paired with row 2 of b[][] has the score of 3.
  • Row 1 of a[][] paired with row 0 of b[][] with score of 2.
  • Row 2 of a[][] paired with row 1 of b[][] with score of 3.

Therefore, the sum of scores obtained is 3 + 2 + 3 = 8.

Input: a[][] = {{0, 0}, {0, 0}, {0, 0}}, b[][] = {{1, 1}, {1, 1}, {1, 1}}
Output: 0

Naive Approach: The simplest approach to solve the given problem is to generate all possible permutations of the rows of the arrays a[][]  and for each permutation of the array a[][], find the sum of scores of each corresponding pair, and if it’s greater than the current answer, update the answer to the value of the current sum of scores. After checking for all the pairs, print the maximum score obtained.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the maximum score
void maxScoreSum(vector<vector<int> >& a,
                 vector<vector<int> >& b)
{
    // Stores the maximum sum of scores
    int maxSum = 0;
 
    vector<int> pos;
    for (int i = 0; i < a.size(); i++) {
        pos.push_back(i);
    }
 
    // For each permutation of pos vector
    // calculate the score
    do {
        int curSum = 0;
        for (int i = 0; i < a.size(); i++) {
 
            for (int j = 0;
                 j < a[pos[i]].size(); j++) {
 
                // If values at current indexes
                // are same then increment the
                // current score
                curSum += (a[pos[i]][j] == b[i][j]);
                maxSum = max(maxSum, curSum);
            }
        }
    } while (next_permutation(pos.begin(), pos.end()));
 
    // Print the maximum score
    cout << maxSum;
}
 
// Driver Code
int main()
{
    int N = 3, M = 3;
    vector<vector<int> > a
        = { { 1, 1, 0 }, { 1, 0, 1 }, { 0, 0, 1 } };
    vector<vector<int> > b
        = { { 1, 0, 0 }, { 0, 0, 1 }, { 1, 1, 0 } };
 
    maxScoreSum(a, b);
 
    return 0;
}


Java




// Java code for the above approach
import java.util.*;
 
class GFG {
 
  public static List<List<Integer> > perms
    = new ArrayList<>();
 
  public static void
    generatePermutations(int mask, int ind, int N,
                         List<Integer> current)
  {
    if (ind == N) {
      List<Integer> temp = new ArrayList<>(current);
      perms.add(temp);
      return;
    }
    for (int i = 0; i < N; i++) {
      if (((mask >> i) & 1) == 0) {
        current.add(i);
        generatePermutations(mask | (1 << i),
                             ind + 1, N, current);
        current.remove(current.size() - 1);
      }
    }
  }
 
  // Function to find the maximum score
  public static void maxScoreSum(List<List<Integer> > a,
                                 List<List<Integer> > b)
  {
    // Stores the maximum sum of scores
    int maxSum = 0;
 
    generatePermutations(0, 0, a.size(),
                         new ArrayList<Integer>());
 
    // For each permutation of {0, a.size() - 1} vector
    // calculate the score
    for (int ind = 0; ind < perms.size(); ind++) {
      List<Integer> pos = perms.get(ind);
      int curSum = 0;
      for (int i = 0; i < a.size(); i++) {
 
        for (int j = 0;
             j < a.get(pos.get(i)).size(); j++) {
 
          // If values at current indexes
          // are same then increment the
          // current score
          curSum += (a.get(pos.get(i)).get(j)
                     == b.get(i).get(j)
                     ? 1
                     : 0);
          maxSum = Math.max(maxSum, curSum);
        }
      }
    }
 
    // Print the maximum score
    System.out.println(maxSum);
  }
 
  // Driver Code
  public static void main(String[] args)
  {
 
    List<List<Integer> > a = new ArrayList<>();
    a.add(Arrays.asList(1, 1, 0));
    a.add(Arrays.asList(1, 0, 1));
    a.add(Arrays.asList(0, 0, 1));
 
    List<List<Integer> > b = new ArrayList<>();
    b.add(Arrays.asList(1, 0, 0));
    b.add(Arrays.asList(0, 0, 1));
    b.add(Arrays.asList(1, 1, 0));
 
    maxScoreSum(a, b);
  }
}
// This code is contributed by ik_9


Python3




# Python Program to implement
# the above approach
def next_permutation(array):
    i = len(array) - 1
    while (i > 0 and array[i - 1] >= array[i]):
        i -= 1
 
    if (i <= 0):
        return False
 
    j = len(array) - 1
 
    while (array[j] <= array[i - 1]):
        j -= 1
 
    temp = array[i - 1]
    array[i - 1] = array[j]
    array[j] = temp
 
    j = len(array) - 1
 
    while (i < j):
        temp = array[i];
        array[i] = array[j];
        array[j] = temp;
        i += 1
        j -= 1
 
    return array
 
# Function to find the maximum score
def maxScoreSum(a, b):
   
    # Stores the maximum sum of scores
    maxSum = 0
 
    pos = []
    for i in range(len(a)):
        pos.append(i)
 
    # For each permutation of pos vector
    # calculate the score
    while(True):
        curSum = 0
        for i in range(len(a)):
 
            for j in range(len(a[pos[i]])):
 
                # If values at current indexes
                # are same then increment the
                # current score
                curSum += (a[pos[i]][j] == b[i][j])
                maxSum = max(maxSum, curSum)
 
        if(next_permutation(pos) == False):
            break
 
    # Print the maximum score
    print(maxSum)
 
# Driver Code
N, M = 3, 3
a = [[1, 1, 0], [1, 0, 1], [0, 0, 1]]
b = [[1, 0, 0], [0, 0, 1], [1, 1, 0]]
 
maxScoreSum(a, b)
 
# This code is contributed by shinjanpatra


C#




// C# program to implement above approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
  public static List<List<int>> perms = new List<List<int>>();
 
  public static void generate_permuatation(int mask, int ind, int N, List<int> current){
    if(ind == N){
      List<int> temp = new List<int>(current);
      perms.Add(temp);
      return;
    }
    for(int i = 0 ; i < N ; i++){
      if(((mask >> i) & 1) == 0){
        current.Add(i);
        generate_permuatation(mask | (1 << i), ind + 1, N, current);
        current.RemoveAt(current.Count-1);
      }
    }
  }
 
  // Function to find the maximum score
  public static void maxScoreSum(List<List<int>> a, List<List<int>> b)
  {
    // Stores the maximum sum of scores
    int maxSum = 0;
 
    generate_permuatation(0, 0, a.Count, new List<int>());
 
    // For each permutation of {0, a.Count - 1} vector
    // calculate the score
    for(int ind = 0 ; ind < perms.Count ; ind++){
      List<int> pos = perms[ind];
      int curSum = 0;
      for (int i = 0; i < a.Count ; i++) {
 
        for (int j = 0 ; j < a[pos[i]].Count ; j++) {
 
          // If values at current indexes
          // are same then increment the
          // current score
          curSum += (a[pos[i]][j] == b[i][j] ? 1 : 0);
          maxSum = Math.Max(maxSum, curSum);
        }
      }
    }
 
    // Print the maximum score
    Console.Write(maxSum);
  }
 
  // Driver Code
  public static void Main(string[] args){
 
    // int N = 3;
    // int M = 3;
    List<List<int>> a = new List<List<int>>{
      new List<int>{ 1, 1, 0 },
      new List<int>{ 1, 0, 1 },
      new List<int>{ 0, 0, 1 }
    };
    List<List<int>> b = new List<List<int>>{
      new List<int>{ 1, 0, 0 },
      new List<int>{ 0, 0, 1 },
      new List<int>{ 1, 1, 0 }
    };
 
    maxScoreSum(a, b);
 
  }
}
 
// This code is contributed by subhamgoyal2014.


Javascript




<script>
        // JavaScript Program to implement
        // the above approach
        function next_permutation(array) {
            var i = array.length - 1;
            while (i > 0 && array[i - 1] >= array[i]) {
                i--;
            }
 
            if (i <= 0) {
                return false;
            }
 
            var j = array.length - 1;
 
            while (array[j] <= array[i - 1]) {
                j--;
            }
 
            var temp = array[i - 1];
            array[i - 1] = array[j];
            array[j] = temp;
 
            j = array.length - 1;
 
            while (i < j) {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
                i++;
                j--;
            }
 
            return array;
        }
        // Function to find the maximum score
        function maxScoreSum(a, b) {
            // Stores the maximum sum of scores
            let maxSum = 0;
 
            let pos = [];
            for (let i = 0; i < a.length; i++) {
                pos.push(i);
            }
 
            // For each permutation of pos vector
            // calculate the score
            do {
                let curSum = 0;
                for (let i = 0; i < a.length; i++) {
 
                    for (let j = 0;
                        j < a[pos[i]].length; j++) {
 
                        // If values at current indexes
                        // are same then increment the
                        // current score
                        curSum += (a[pos[i]][j] == b[i][j]);
                        maxSum = Math.max(maxSum, curSum);
                    }
                }
            } while (next_permutation(pos));
 
            // Print the maximum score
            document.write(maxSum);
        }
 
        // Driver Code
 
        let N = 3, M = 3;
        let a
            = [[1, 1, 0], [1, 0, 1], [0, 0, 1]];
        let b
            = [[1, 0, 0], [0, 0, 1], [1, 1, 0]];
 
        maxScoreSum(a, b);
 
     // This code is contributed by Potta Lokesh
 
    </script>


Output: 

8

 

Time Complexity: O(N*M*M!), where M! are the number of permutations and N*M for calculating the score of each pair.
Auxiliary Space: O(M)

Efficient Approach: The above approach can also be optimized using the concept of Bitmasking, The idea is for each row in vector a[][], try all rows in vector b[][] that haven’t been chosen before. Use a bitmask to represent already chosen rows of vector b[][]. To avoid re-computing the same subproblem, memoize the result for each bitmask. Follow the steps below to solve the problem:

  • Initialize the variables row as 0, mask as (2M – 1).
  • Initialize the vector dp[] of size mask + 1 with values -1.
  • If row is greater than equal to a.size() then return 0 and if dp[mask] is not equal to -1 then return dp[mask].
  • Initialize the variable ans as 0 to store the answer.
  • Iterate over the range [0, a.size()) using the variable i and perform the following tasks:
    • If the bitwise AND of mask and 2i is true then initialize the variable newMask as mask^(1<<i) and curSum as 0.
    • Iterate over the range [0, a[i].size()) using the variable j and if a[row][j] equals b[i][j] then increase the value of curSum by 1.
    • Set the value of ans as the maximum of ans or curSum + maxScoreSum(a, b, row+1, newmask, dp) recursively.
  • After performing the above steps, set the value of dp[mask] as ans and return the value of ans as the answer.
     

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the maximum defined
// score
int maxScoreSum(vector<vector<int> >& a,
                vector<vector<int> >& b,
                int row, int mask,
                vector<int>& dp)
{
    // If all students are assigned
    if (row >= a.size()) {
        return 0;
    }
    if (dp[mask] != -1) {
        return dp[mask];
    }
 
    int ans = 0;
 
    for (int i = 0; i < a.size(); i++) {
 
        // Check if row is not paired yet
        if (mask & (1 << i)) {
            int newMask = mask ^ (1 << i);
            int curSum = 0;
 
            // Check for all indexes
            for (int j = 0; j < a[i].size(); j++) {
 
                // If values at current indexes
                // are same increase curSum
                if (a[row][j] == b[i][j]) {
                    curSum++;
                }
            }
 
            // Further recursive call
            ans = max(
                ans, curSum
                         + maxScoreSum(
                               a, b, row + 1,
                               newMask, dp));
        }
    }
 
    // Store the ans for current
    // mask and return
    return dp[mask] = ans;
}
 
// Utility function to find the maximum
// defined score
int maxScoreSumUtil(vector<vector<int> >& a,
                    vector<vector<int> >& b,
                    int N, int M)
{
    int row = 0;
 
    // Create a mask with all set bits
    // 1 -> row is not paired yet
    // 0 -> row is already paired
    int mask = pow(2, M) - 1;
 
    // Initialise dp array with -1
    vector<int> dp(mask + 1, -1);
 
    return maxScoreSum(a, b, row, mask, dp);
}
 
// Driver Code
int main()
{
    int N = 3, M = 3;
    vector<vector<int> > a
        = { { 1, 1, 0 }, { 1, 0, 1 }, { 0, 0, 1 } };
    vector<vector<int> > b
        = { { 1, 0, 0 }, { 0, 0, 1 }, { 1, 1, 0 } };
 
    cout << maxScoreSumUtil(a, b, N, M);
 
    return 0;
}


Java




import java.util.ArrayList;
import java.util.List;
 
class GFG {
    // Function to find the maximum defined
    // score
    public static int maxScoreSum(List<List<Integer> > a,
                                  List<List<Integer> > b,
                                  int row, int mask,
                                  int[] dp)
    {
        // If all students are assigned
        if (row >= a.size()) {
            return 0;
        }
        if (dp[mask] != -1) {
            return dp[mask];
        }
 
        int ans = 0;
 
        for (int i = 0; i < a.size(); i++) {
 
            // Check if row is not paired yet
            if ((mask & (1 << i)) > 0) {
                int newMask = mask ^ (1 << i);
                int curSum = 0;
 
                // Check for all indexes
                for (int j = 0; j < a.get(i).size(); j++) {
 
                    // If values at current indexes
                    // are same increase curSum
                    if (a.get(row).get(j)
                        == b.get(i).get(j)) {
                        curSum++;
                    }
                }
 
                // Further recursive call
                ans = Math.max(
                    ans, curSum
                             + maxScoreSum(a, b, row + 1,
                                           newMask, dp));
            }
        }
 
        // Store the ans for current
        // mask and return
        return dp[mask] = ans;
    }
 
    // Utility function to find the maximum
    // defined score
    public static int
    maxScoreSumUtil(List<List<Integer> > a,
                    List<List<Integer> > b, int N, int M)
    {
        int row = 0;
 
        // Create a mask with all set bits
        // 1 -> row is not paired yet
        // 0 -> row is already paired
        int mask = (int)Math.pow(2, M) - 1;
 
        // Initialise dp array with -1
        int[] dp = new int[1 << M];
        for (int i = 0; i <= mask; i++) {
            dp[i] = -1;
        }
 
        return maxScoreSum(a, b, row, mask, dp);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
 
        int N = 3;
        int M = 3;
        List<List<Integer> > a
            = new ArrayList<List<Integer> >() {
                  {
                      add(new ArrayList<Integer>() {
                          {
                              add(1);
                              add(1);
                              add(0);
                          }
                      });
                      add(new ArrayList<Integer>() {
                          {
                              add(1);
                              add(0);
                              add(1);
                          }
                      });
                      add(new ArrayList<Integer>() {
                          {
                              add(0);
                              add(0);
                              add(1);
                          }
                      });
                  }
              };
        List<List<Integer> > b
            = new ArrayList<List<Integer> >() {
                  {
                      add(new ArrayList<Integer>() {
                          {
                              add(1);
                              add(0);
                              add(0);
                          }
                      });
                      add(new ArrayList<Integer>() {
                          {
                              add(0);
                              add(0);
                              add(1);
                          }
                      });
                      add(new ArrayList<Integer>() {
                          {
                              add(1);
                              add(1);
                              add(0);
                          }
                      });
                  }
              };
 
        System.out.println(maxScoreSumUtil(a, b, N, M));
    }
}


Python3




# Python 3 program for the above approach
 
# Function to find the maximum defined
# score
def maxScoreSum(a, b, row, mask, dp):
 
    # If all students are assigned
    if (row >= len(a)):
        return 0
 
    if (dp[mask] != -1):
        return dp[mask]
 
    ans = 0
 
    for i in range(len(a)):
 
        # Check if row is not paired yet
        if (mask & (1 << i)):
            newMask = mask ^ (1 << i)
            curSum = 0
 
            # Check for all indexes
            for j in range(len(a[i])):
 
                # If values at current indexes
                # are same increase curSum
                if (a[row][j] == b[i][j]):
                    curSum += 1
 
            # Further recursive call
            ans = max(
                ans, curSum
                + maxScoreSum(
                    a, b, row + 1,
                    newMask, dp))
 
    # Store the ans for current
    # mask and return
    dp[mask] = ans
    return dp[mask]
 
# Utility function to find the maximum
# defined score
def maxScoreSumUtil(a,
                    b,
                    N, M):
 
    row = 0
 
    # Create a mask with all set bits
    # 1 -> row is not paired yet
    # 0 -> row is already paired
    mask = pow(2, M) - 1
 
    # Initialise dp array with -1
    dp = [-1]*(mask + 1)
 
    return maxScoreSum(a, b, row, mask, dp)
 
# Driver Code
if __name__ == "__main__":
 
    N = 3
    M = 3
    a = [[1, 1, 0], [1, 0, 1], [0, 0, 1]]
    b = [[1, 0, 0], [0, 0, 1], [1, 1, 0]]
 
    print(maxScoreSumUtil(a, b, N, M))
 
    # This code is contributed by ukasp.


C#




// C# program to implement above approach
using System;
using System.Collections.Generic;
 
class GFG
{
    // Function to find the maximum defined
    // score
    public static int maxScoreSum(List<List<int>> a, List<List<int>> b, int row, int mask, List<int> dp)
    {
        // If all students are assigned
        if (row >= a.Count){
            return 0;
        }
        if (dp[mask] != -1){
            return dp[mask];
        }
     
        int ans = 0;
  
        for (int i = 0 ; i < a.Count ; i++) {
     
            // Check if row is not paired yet
            if ((mask & (1 << i)) > 0){
                int newMask = mask ^ (1 << i);
                int curSum = 0;
     
                // Check for all indexes
                for (int j = 0; j < a[i].Count ; j++) {
     
                    // If values at current indexes
                    // are same increase curSum
                    if (a[row][j] == b[i][j]) {
                        curSum++;
                    }
                }
     
                // Further recursive call
                ans = Math.Max(ans, curSum + maxScoreSum(a, b, row + 1, newMask, dp));
            }
        }
     
        // Store the ans for current
        // mask and return
        return dp[mask] = ans;
    }
     
    // Utility function to find the maximum
    // defined score
    public static int maxScoreSumUtil(List<List<int>> a, List<List<int>> b, int N,int M)
    {
        int row = 0;
  
        // Create a mask with all set bits
        // 1 -> row is not paired yet
        // 0 -> row is already paired
        int mask = (int)Math.Pow(2, M) - 1;
     
        // Initialise dp array with -1
        List<int> dp = new List<int>();
        for(int i = 0 ; i <= mask ; i++){
            dp.Add(-1);
        }
     
        return maxScoreSum(a, b, row, mask, dp);
    }
 
    // Driver Code
    public static void Main(string[] args){
         
        int N = 3;
        int M = 3;
        List<List<int>> a = new List<List<int>>{
            new List<int>{ 1, 1, 0 },
            new List<int>{ 1, 0, 1 },
            new List<int>{ 0, 0, 1 }
        };
        List<List<int>> b = new List<List<int>>{
            new List<int>{ 1, 0, 0 },
            new List<int>{ 0, 0, 1 },
            new List<int>{ 1, 1, 0 }
        };
 
        Console.Write(maxScoreSumUtil(a, b, N, M));
 
    }
}
 
// This code is contributed by subhamgoyal2014.


Javascript




<script>
 
// JavaScript code for the approach
 
// Function to find the maximum defined
// score
function maxScoreSum(a, b, row, mask, dp){
 
    // If all students are assigned
    if (row >= a.length)
        return 0
 
    if (dp[mask] != -1)
        return dp[mask]
 
    let ans = 0
 
    for(let i=0;i<a.length;i++){
 
        // Check if row is not paired yet
        if (mask & (1 << i)){
            newMask = mask ^ (1 << i)
            curSum = 0
 
            // Check for all indexes
            for(let j=0;j<a[i].length;j++){
 
                // If values at current indexes
                // are same increase curSum
                if (a[row][j] == b[i][j])
                    curSum += 1
            }
 
            // Further recursive call
            ans = Math.max(ans, curSum + maxScoreSum(a, b, row + 1,newMask, dp))
 
        }
 
    }   
 
    // Store the ans for current
    // mask and return
    dp[mask] = ans
    return dp[mask]
 
}
 
// Utility function to find the maximum
// defined score
function maxScoreSumUtil(a,b,N, M){
 
    let row = 0
 
    // Create a mask with all set bits
    // 1 -> row is not paired yet
    // 0 -> row is already paired
    let mask = Math.pow(2, M) - 1
 
    // Initialise dp array with -1
    let dp = new Array(mask + 1).fill(-1)
 
    return maxScoreSum(a, b, row, mask, dp)
 
}
 
// Driver Code
let N = 3
let M = 3
let a = [[1, 1, 0], [1, 0, 1], [0, 0, 1]]
let b = [[1, 0, 0], [0, 0, 1], [1, 1, 0]]
 
document.write(maxScoreSumUtil(a, b, N, M),"</br>")
 
// This code is contributed by shinjanpatra
 
</script>


Output: 

8

 

Time Complexity: O(2M*M*N)
Auxiliary Space: O(2M)

 



Last Updated : 09 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads