Minimum swaps to build valid Chessboard
Last Updated :
05 Aug, 2022
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:
- 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.
- 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++
#include <bits/stdc++.h>
using namespace std;
int movesToChessboard(vector<vector< int > >& board)
{
int n = board.size();
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;
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 (rowsum != n / 2 and rowsum != (n + 1) / 2)
return -1;
if (colsum != n / 2 and colsum != (n + 1) / 2)
return -1;
if (n % 2) {
if (rowswap % 2)
rowswap = n - rowswap;
if (colswap % 2)
colswap = n - colswap;
}
else {
rowswap = min(rowswap, n - rowswap);
colswap = min(colswap, n - colswap);
}
return (rowswap + colswap) / 2;
}
int main()
{
vector<vector< int > > arr{ { 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 1, 0, 0, 1 },
{ 1, 0, 0, 1 } };
int minswap = movesToChessboard(arr);
if (minswap == -1)
cout << "Impossible" ;
else
cout << minswap << endl;
return 0;
}
|
Java
import java.io.*;
class GFG {
public static int movesToChessboard( int board[][])
{
int n = board.length;
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 ;
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 (rowsum != n / 2 && rowsum != (n + 1 ) / 2 )
return - 1 ;
if (colsum != n / 2 && colsum != (n + 1 ) / 2 )
return - 1 ;
if (n % 2 != 0 ) {
if (rowswap % 2 != 0 )
rowswap = n - rowswap;
if (colswap % 2 != 0 )
colswap = n - colswap;
}
else {
rowswap = Math.min(rowswap, n - rowswap);
colswap = Math.min(colswap, n - colswap);
}
return (rowswap + colswap + 2 ) / 2 ;
}
public static void main(String[] args)
{
int arr[][] = { { 0 , 1 , 1 , 0 },
{ 0 , 1 , 1 , 0 },
{ 1 , 0 , 0 , 1 },
{ 1 , 0 , 0 , 1 } };
int minswap = movesToChessboard(arr);
if (minswap == - 1 )
System.out.print( "Impossible" );
else
System.out.print(minswap);
}
}
|
Python3
def movesToChessboard(board):
n = len (board)
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
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 (rowsum ! = n / / 2 and rowsum ! = (n + 1 ) / / 2 ):
return - 1
if (colsum ! = n / / 2 and colsum ! = (n + 1 ) / / 2 ):
return - 1
if (n % 2 ):
if (rowswap % 2 ):
rowswap = n - rowswap
if (colswap % 2 ):
colswap = n - colswap
else :
rowswap = min (rowswap, n - rowswap)
colswap = min (colswap, n - colswap)
return (rowswap + colswap) / / 2
if __name__ = = "__main__" :
arr = [[ 0 , 1 , 1 , 0 ],
[ 0 , 1 , 1 , 0 ],
[ 1 , 0 , 0 , 1 ],
[ 1 , 0 , 0 , 1 ]]
minswap = movesToChessboard(arr)
if (minswap = = - 1 ):
print ( "Impossible" )
else :
print (minswap)
|
C#
using System;
class GFG {
public static int movesToChessboard( int [,] board)
{
int n = board.GetLength(0);
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;
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 (rowsum != n / 2 && rowsum != (n + 1) / 2)
return -1;
if (colsum != n / 2 && colsum != (n + 1) / 2)
return -1;
if (n % 2 != 0) {
if (rowswap % 2 != 0)
rowswap = n - rowswap;
if (colswap % 2 != 0)
colswap = n - colswap;
}
else {
rowswap = Math.Min(rowswap, n - rowswap);
colswap = Math.Min(colswap, n - colswap);
}
return (rowswap + colswap + 2) / 2;
}
public static void Main()
{
int [,] arr = { { 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 1, 0, 0, 1 },
{ 1, 0, 0, 1 } };
int minswap = movesToChessboard(arr);
if (minswap == -1)
Console.Write( "Impossible" );
else
Console.Write(minswap);
}
}
|
Javascript
<script>
function movesToChessboard( board)
{
let n = board.length;
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;
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 (rowsum != n / 2 && rowsum != (n + 1) / 2)
return -1;
if (colsum != n / 2 && colsum != (n + 1) / 2)
return -1;
if (n % 2) {
if (rowswap % 2)
rowswap = n - rowswap;
if (colswap % 2)
colswap = n - colswap;
}
else {
rowswap = Math.min(rowswap, n - rowswap);
colswap = Math.min(colswap, n - colswap);
}
return (rowswap + colswap) / 2;
}
let arr = [ [ 0, 1, 1, 0 ],
[ 0, 1, 1, 0 ],
[ 1, 0, 0, 1 ],
[ 1, 0, 0, 1 ]];
let minswap = movesToChessboard(arr);
if (minswap == -1)
document.write( "Impossible" );
else
document.write(minswap);
</script>
|
Time complexity: O(N2)
Auxiliary Space: O(1)
Share your thoughts in the comments
Please Login to comment...