Open In App

Minimum swaps to build valid Chessboard

Last Updated : 05 Aug, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Given a matrix of size N * N containing only 0s and 1s, where 0 represents white and 1 represents black. The task is to minimize the number of swaps to form a valid chessboard. Only 2 rows or 2 columns can be swapped with each other.
If it is impossible to form a chessboard, return -1.

Examples:

Input: {{0, 1, 1, 0}, {0, 1, 1, 0}, {1, 0, 0, 1}, {1, 0, 0, 1}}
Output: 2
Explanation: One potential sequence of moves is shown below,  
The first move swaps the first and second columns.
The second move swaps the second and third row.

Input: {{0, 1, 0}, {1, 0, 1}, {1, 1, 0}}
Output: -1

 

Approach: The problem can be solved based on the following properties of chessboard and the observation:

Properties of chess board:

  1. In a valid chess board, there are 2 and only 2 kinds of rows and one is inverse to the other, the same is true for columns.
    A corollary is that any rectangle inside the board with corners top left, top right, bottom left, and bottom right must be 4 zeros or 2 ones and 2 zeros or 4 zeros.
  2. Another important property is that every row and column has half ones. Assume the board is N * N:
    • If N = 2 * K, every row and every column has K ones and K zeros.
    • If N = 2 * K + 1, every row and every column has K ones and K + 1 zeros or K + 1 ones and K zeros.

Since the swap process does not break these properties, for a given board to be valid, these properties must hold.
These two conditions are necessary and sufficient conditions for a valid chessboard.

Swap Count:

To calculate the number of swaps required to create the chessboard, Iterating over first row and first column and check for alternate whites and blacks. 

Follow the steps mentioned below to implement the idea:

  • Initially, check whether the board is valid or not using the properties of the chessboard, if the board is valid we proceed otherwise -1 is returned.
  • Iterate over the first row and the first column and count the number of 1s in both and also count the number of swaps required using the condition, A[i] = i%2 .
  • Use the number of ones calculated to verify the second property of the chessboard (i.e. every row and column has half ones), if the board is invalid return -1 otherwise proceed further. 
  • Now if N is even, then the minimum swaps are stored as they are.
  • If N is Odd, then we take the even swaps as we can swap 2 rows or 2 columns only.

Below is the implementation of the above approach.

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to return minimum swaps
int movesToChessboard(vector<vector<int> >& board)
{
    int n = board.size();
 
    // Loop to check whether the board
    // can be made valid or not
    for (int r = 0; r < n; r++) {
        for (int c = 0; c < n; c++) {
            if (board[0][0] ^ board[r][0] ^ board[0]
                ^ board[r] == 1) {
                return -1;
            }
        }
    }
 
    int rowsum = 0;
    int colsum = 0;
    int rowswap = 0;
    int colswap = 0;
 
    // Loop to calculate sum and swap
    for (int i = 0; i < n; i++) {
        rowsum += board[i][0];
        colsum += board[0][i];
        rowswap += board[i][0] == i % 2;
        colswap += board[0][i] == i % 2;
    }
 
    // If there are more white or more black
    if (rowsum != n / 2 and rowsum != (n + 1) / 2)
        return -1;
    if (colsum != n / 2 and colsum != (n + 1) / 2)
        return -1;
 
    // If n is odd
    if (n % 2) {
        if (rowswap % 2)
            rowswap = n - rowswap;
        if (colswap % 2)
            colswap = n - colswap;
    }
 
    // If n is even
    else {
        rowswap = min(rowswap, n - rowswap);
        colswap = min(colswap, n - colswap);
    }
 
    // Return the ans
    return (rowswap + colswap) / 2;
}
 
// Driver Code
int main()
{
    // Given vector array
    vector<vector<int> > arr{ { 0, 1, 1, 0 },
                              { 0, 1, 1, 0 },
                              { 1, 0, 0, 1 },
                              { 1, 0, 0, 1 } };
 
    // Function call
    int minswap = movesToChessboard(arr);
 
    // Printing the output
    if (minswap == -1)
        cout << "Impossible";
    else
        cout << minswap << endl;
    return 0;
}


Java




// Java code to implement the approach
import java.io.*;
 
class GFG {
    // Function to return minimum swaps
    public static int movesToChessboard(int board[][])
    {
        int n = board.length;
 
        // Loop to check whether the board
        // can be made valid or not
        for (int r = 0; r < n; r++) {
            for (int c = 0; c < n; c++) {
                if ((board[0][0] ^ board[r][0] ^ board[0]
                     ^ board[r])
                    == 1) {
                    return -1;
                }
            }
        }
 
        int rowsum = 0;
        int colsum = 0;
        int rowswap = 0;
        int colswap = 0;
 
        // Loop to calculate sum and swap
        for (int i = 0; i < n; i++) {
            rowsum += board[i][0];
            colsum += board[0][i];
            if (i % 2 != 0) {
                rowswap += board[i][0];
                colswap += board[0][i];
            }
        }
 
        // If there are more white or more black
        if (rowsum != n / 2 && rowsum != (n + 1) / 2)
            return -1;
        if (colsum != n / 2 && colsum != (n + 1) / 2)
            return -1;
 
        // If n is odd
        if (n % 2 != 0) {
            if (rowswap % 2 != 0)
                rowswap = n - rowswap;
            if (colswap % 2 != 0)
                colswap = n - colswap;
        }
 
        // If n is even
        else {
            rowswap = Math.min(rowswap, n - rowswap);
            colswap = Math.min(colswap, n - colswap);
        }
 
        // Return the ans
        return (rowswap + colswap + 2) / 2;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Given vector array
        int arr[][] = { { 0, 1, 1, 0 },
                        { 0, 1, 1, 0 },
                        { 1, 0, 0, 1 },
                        { 1, 0, 0, 1 } };
 
        // Function call
        int minswap = movesToChessboard(arr);
 
        // Printing the output
        if (minswap == -1)
            System.out.print("Impossible");
        else
            System.out.print(minswap);
    }
}
 
// This code is contributed by Rohit Pradhan


Python3




# python3 code to implement the approach
 
# Function to return minimum swaps
 
 
def movesToChessboard(board):
 
    n = len(board)
 
    # Loop to check whether the board
    # can be made valid or not
    for r in range(0, n):
        for c in range(0, n):
            if (board[0][0] ^ board[r][0] ^ board[0] ^ board[r] == 1):
                return -1
 
    rowsum = 0
    colsum = 0
    rowswap = 0
    colswap = 0
 
    # Loop to calculate sum and swap
    for i in range(0, n):
        rowsum += board[i][0]
        colsum += board[0][i]
        rowswap += board[i][0] == i % 2
        colswap += board[0][i] == i % 2
 
    # If there are more white or more black
    if (rowsum != n // 2 and rowsum != (n + 1) // 2):
        return -1
    if (colsum != n // 2 and colsum != (n + 1) // 2):
        return -1
 
    # If n is odd
    if (n % 2):
        if (rowswap % 2):
            rowswap = n - rowswap
        if (colswap % 2):
            colswap = n - colswap
 
    # If n is even
    else:
        rowswap = min(rowswap, n - rowswap)
        colswap = min(colswap, n - colswap)
 
    # Return the ans
    return (rowswap + colswap) // 2
 
 
# Driver Code
if __name__ == "__main__":
 
    # Given vector array
    arr = [[0, 1, 1, 0],
           [0, 1, 1, 0],
           [1, 0, 0, 1],
           [1, 0, 0, 1]]
 
    # Function call
    minswap = movesToChessboard(arr)
 
    # Printing the output
    if (minswap == -1):
        print("Impossible")
    else:
        print(minswap)
 
  # This code is contributed by rakeshsahni


C#




// C# program for above approach:
using System;
class GFG {
 
  // Function to return minimum swaps
  public static int movesToChessboard(int[,] board)
  {
    int n = board.GetLength(0);
 
    // Loop to check whether the board
    // can be made valid or not
    for (int r = 0; r < n; r++) {
      for (int c = 0; c < n; c++) {
        if ((board[0,0] ^ board[r,0] ^ board[0,c]
             ^ board[r,c])
            == 1) {
          return -1;
        }
      }
    }
 
    int rowsum = 0;
    int colsum = 0;
    int rowswap = 0;
    int colswap = 0;
 
    // Loop to calculate sum and swap
    for (int i = 0; i < n; i++) {
      rowsum += board[i,0];
      colsum += board[0,i];
      if (i % 2 != 0) {
        rowswap += board[i,0];
        colswap += board[0,i];
      }
    }
 
    // If there are more white or more black
    if (rowsum != n / 2 && rowsum != (n + 1) / 2)
      return -1;
    if (colsum != n / 2 && colsum != (n + 1) / 2)
      return -1;
 
    // If n is odd
    if (n % 2 != 0) {
      if (rowswap % 2 != 0)
        rowswap = n - rowswap;
      if (colswap % 2 != 0)
        colswap = n - colswap;
    }
 
    // If n is even
    else {
      rowswap = Math.Min(rowswap, n - rowswap);
      colswap = Math.Min(colswap, n - colswap);
    }
 
    // Return the ans
    return (rowswap + colswap + 2) / 2;
  }
 
  // Driver Code
  public static void Main()
  {
    // Given vector array
    int[,] arr = { { 0, 1, 1, 0 },
                  { 0, 1, 1, 0 },
                  { 1, 0, 0, 1 },
                  { 1, 0, 0, 1 } };
 
    // Function call
    int minswap = movesToChessboard(arr);
 
    // Printing the output
    if (minswap == -1)
      Console.Write("Impossible");
    else
      Console.Write(minswap);
  }
}
 
// This code is contributed by code_hunt.


Javascript




<script>
//Javascript code for the above approach
 
// Function to return minimum swaps
function movesToChessboard( board)
{
    let n = board.length;
 
    // Loop to check whether the board
    // can be made valid or not
    for (let r = 0; r < n; r++) {
        for (let c = 0; c < n; c++) {
            if (board[0][0] ^ board[r][0] ^ board[0]
                ^ board[r] == 1) {
                return -1;
            }
        }
    }
 
    let rowsum = 0;
    let colsum = 0;
    let rowswap = 0;
    let colswap = 0;
 
    // Loop to calculate sum and swap
    for (let i = 0; i < n; i++) {
        rowsum += board[i][0];
        colsum += board[0][i];
        rowswap += board[i][0] == i % 2;
        colswap += board[0][i] == i % 2;
    }
 
    // If there are more white or more black
    if (rowsum != n / 2 && rowsum != (n + 1) / 2)
        return -1;
    if (colsum != n / 2 && colsum != (n + 1) / 2)
        return -1;
 
    // If n is odd
    if (n % 2) {
        if (rowswap % 2)
            rowswap = n - rowswap;
        if (colswap % 2)
            colswap = n - colswap;
    }
 
    // If n is even
    else {
        rowswap = Math.min(rowswap, n - rowswap);
        colswap = Math.min(colswap, n - colswap);
    }
 
    // Return the ans
    return (rowswap + colswap) / 2;
}
 
// Driver Code
    //2d array
    let arr  = [ [ 0, 1, 1, 0 ],
                              [ 0, 1, 1, 0 ],
                              [ 1, 0, 0, 1 ],
                              [ 1, 0, 0, 1 ]];
 
    // Function call
    let minswap = movesToChessboard(arr);
 
    // Printing the output
    if (minswap == -1)
        document.write( "Impossible");
    else
         document.write(minswap);
          
         // This code is contributed by hrithikgarg03188.
</script>


Output

2

Time complexity: O(N2
Auxiliary Space: O(1)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads