Given two integers N and K, the task is to find the number of ways to place K bishops on an N × N chessboard so that no two bishops attack each other.
Here is an example for a 5×5 chessboard.
Examples:
Input: N = 2, K = 2
Output: 4
The different ways to place 2 bishops in a 2 * 2 chessboard are :
Input: N = 4, K = 3
Output: 232
Approach: This problem can be solved using dynamic programming.
- Let dp[i][j] denote the number of ways to place j bishops on diagonals with indices up to i which have the same color as diagonal i. Then i = 1…2N-1 and j = 0…K.
- We can calculate dp[i][j] using only values of dp[i-2] (we subtract 2 because we only consider diagonals of the same color as i). There are two ways to get dp[i][j]. Either we place all j bishops on previous diagonals: then there are dp[i-2][j] ways to achieve this. Or we place one bishop on diagonal i and j-1 bishops on previous diagonals. The number of ways to do this equals the number of squares in diagonal i – (j – 1), because each of j-1 bishops placed on previous diagonals will block one square on the current diagonal.
- The base case is simple: dp[i][0] = 1, dp[1][1] = 1.
- Once we have calculated all values of dp[i][j], the answer can be obtained as follows: consider all possible numbers of bishops placed on black diagonals i=0…K, with corresponding numbers of bishops on white diagonals K-i. The bishops placed on black and white diagonals never attack each other, so the placements can be done independently. The index of the last black diagonal is 2N-1, the last white one is 2N-2. For each i we add dp[2N-1][i] * dp[2N-2][K-i] to the answer.
Below is the implementation of the above approach:
// CPP implementation of the approach #include<bits/stdc++.h> using namespace std;
// returns the number of squares in diagonal i int squares( int i)
{ if ((i & 1) == 1)
return i / 4 * 2 + 1;
else
return (i - 1) / 4 * 2 + 2;
} // returns the number of ways to fill a // n * n chessboard with k bishops so // that no two bishops attack each other. long bishop_placements( int n, int k)
{ // return 0 if the number of valid places to be
// filled is less than the number of bishops
if (k > 2 * n - 1)
return 0;
// dp table to store the values
long dp[n * 2][k + 1];
// Setting the base conditions
for ( int i = 0; i < n * 2; i++)
{
for ( int j = 0; j < k + 1; j++)
{
dp[i][j] = 0;
}
}
for ( int i = 0; i < n * 2; i++)
dp[i][0] = 1;
dp[1][1] = 1;
// calculate the required number of ways
for ( int i = 2; i < n * 2; i++)
{
for ( int j = 1; j <= k; j++)
{
dp[i][j] = dp[i - 2][j]
+ dp[i - 2][j - 1] * (squares(i) - j + 1);
}
}
// stores the answer
long ans = 0;
for ( int i = 0; i <= k; i++)
{
ans += dp[n * 2 - 1][i] * dp[n * 2 - 2][k - i];
}
return ans;
} // Driver code int main()
{ int n = 2;
int k = 2;
long ans = bishop_placements(n, k);
cout << (ans);
} // This code is contributed by Rajput-Ji |
// Java implementation of the approach class GFG {
// returns the number of squares in diagonal i
static int squares( int i)
{
if ((i & 1 ) == 1 )
return i / 4 * 2 + 1 ;
else
return (i - 1 ) / 4 * 2 + 2 ;
}
// returns the number of ways to fill a
// n * n chessboard with k bishops so
// that no two bishops attack each other.
static long bishop_placements( int n, int k)
{
// return 0 if the number of valid places to be
// filled is less than the number of bishops
if (k > 2 * n - 1 )
return 0 ;
// dp table to store the values
long [][] dp = new long [n * 2 ][k + 1 ];
// Setting the base conditions
for ( int i = 0 ; i < n * 2 ; i++)
dp[i][ 0 ] = 1 ;
dp[ 1 ][ 1 ] = 1 ;
// calculate the required number of ways
for ( int i = 2 ; i < n * 2 ; i++) {
for ( int j = 1 ; j <= k; j++)
dp[i][j]
= dp[i - 2 ][j]
+ dp[i - 2 ][j - 1 ] * (squares(i) - j + 1 );
}
// stores the answer
long ans = 0 ;
for ( int i = 0 ; i <= k; i++) {
ans += dp[n * 2 - 1 ][i] * dp[n * 2 - 2 ][k - i];
}
return ans;
}
// Driver code
public static void main(String[] args)
{
int n = 2 ;
int k = 2 ;
long ans = bishop_placements(n, k);
System.out.println(ans);
}
} |
# Python 3 implementation of the approach # returns the number of squares in # diagonal i def squares(i):
if ((i & 1 ) = = 1 ):
return int (i / 4 ) * 2 + 1
else :
return int ((i - 1 ) / 4 ) * 2 + 2
# returns the number of ways to fill a # n * n chessboard with k bishops so # that no two bishops attack each other. def bishop_placements(n, k):
# return 0 if the number of valid places
# to be filled is less than the number
# of bishops
if (k > 2 * n - 1 ):
return 0
# dp table to store the values
dp = [[ 0 for i in range (k + 1 )]
for i in range (n * 2 )]
# Setting the base conditions
for i in range (n * 2 ):
dp[i][ 0 ] = 1
dp[ 1 ][ 1 ] = 1
# calculate the required number of ways
for i in range ( 2 , n * 2 , 1 ):
for j in range ( 1 , k + 1 , 1 ):
dp[i][j] = (dp[i - 2 ][j] +
dp[i - 2 ][j - 1 ] *
(squares(i) - j + 1 ))
# stores the answer
ans = 0
for i in range ( 0 , k + 1 , 1 ):
ans + = (dp[n * 2 - 1 ][i] *
dp[n * 2 - 2 ][k - i])
return ans
# Driver code if __name__ = = '__main__' :
n = 2
k = 2
ans = bishop_placements(n, k)
print (ans)
# This code is contributed by # Sanjit_Prasad |
// C# implementation of the approach using System;
class GFG
{ // returns the number of squares // in diagonal i static int squares( int i)
{ if ((i & 1) == 1)
return i / 4 * 2 + 1;
else
return (i - 1) / 4 * 2 + 2;
} // returns the number of ways to fill a // n * n chessboard with k bishops so // that no two bishops attack each other. static long bishop_placements( int n, int k)
{ // return 0 if the number of valid
// places to be filled is less than
// the number of bishops
if (k > 2 * n - 1)
return 0;
// dp table to store the values
long [,] dp = new long [n * 2, k + 1];
// Setting the base conditions
for ( int i = 0; i < n * 2; i++)
dp[i, 0] = 1;
dp[1, 1] = 1;
// calculate the required
// number of ways
for ( int i = 2; i < n * 2; i++)
{
for ( int j = 1; j <= k; j++)
dp[i, j] = dp[i - 2, j] +
dp[i - 2, j - 1] *
(squares(i) - j + 1);
}
// stores the answer
long ans = 0;
for ( int i = 0; i <= k; i++)
{
ans += dp[n * 2 - 1, i] *
dp[n * 2 - 2, k - i];
}
return ans;
} // Driver code static public void Main ()
{ int n = 2;
int k = 2;
long ans = bishop_placements(n, k);
Console.WriteLine(ans);
} } // This code is contributed by akt_mit |
<?php // PHP implementation of the approach // returns the number of squares // in diagonal i function squares( $i )
{ if (( $i & 1) == 1)
return intval ( $i / 4) * 2 + 1;
else
return intval (( $i - 1) / 4) * 2 + 2;
} // returns the number of ways to fill a // n * n chessboard with k bishops so // that no two bishops attack each other. function bishop_placements( $n , $k )
{ // return 0 if the number of valid
// places to be filled is less than
// the number of bishops
if ( $k > 2 * $n - 1)
return 0;
// dp table to store the values
$dp = array_fill (0, $n * 2,
array_fill (0, $k + 1, NULL));
// Setting the base conditions
for ( $i = 0; $i < $n * 2; $i ++)
$dp [ $i ][0] = 1;
$dp [1][1] = 1;
// calculate the required number of ways
for ( $i = 2; $i < $n * 2; $i ++)
{
for ( $j = 1; $j <= $k ; $j ++)
$dp [ $i ][ $j ] = $dp [ $i - 2][ $j ] +
$dp [ $i - 2][ $j - 1] *
(squares( $i ) - $j + 1);
}
// stores the answer
$ans = 0;
for ( $i = 0; $i <= $k ; $i ++)
{
$ans += $dp [ $n * 2 - 1][ $i ] *
$dp [ $n * 2 - 2][ $k - $i ];
}
return $ans ;
} // Driver code $n = 2;
$k = 2;
$ans = bishop_placements( $n , $k );
echo $ans ;
// This code is contributed by ita_c ?> |
<script> // Javascript implementation of the approach
// returns the number of squares
// in diagonal i
function squares(i)
{
if ((i & 1) == 1)
return parseInt(i / 4, 10) * 2 + 1;
else
return parseInt((i - 1) / 4, 10) * 2 + 2;
}
// returns the number of ways to fill a
// n * n chessboard with k bishops so
// that no two bishops attack each other.
function bishop_placements(n, k)
{
// return 0 if the number of valid
// places to be filled is less than
// the number of bishops
if (k > 2 * n - 1)
return 0;
// dp table to store the values
let dp = new Array(n * 2);
// Setting the base conditions
for (let i = 0; i < n * 2; i++)
{
dp[i] = new Array(k + 1);
for (let j = 0; j < k + 1; j++)
{
dp[i][j] = 0;
}
dp[i][0] = 1;
}
dp[1][1] = 1;
// calculate the required
// number of ways
for (let i = 2; i < n * 2; i++)
{
for (let j = 1; j <= k; j++)
dp[i][j] = dp[i - 2][j] +
dp[i - 2][j - 1] *
(squares(i) - j + 1);
}
// stores the answer
let ans = 0;
for (let i = 0; i <= k; i++)
{
ans += dp[n * 2 - 1][i] *
dp[n * 2 - 2][k - i];
}
return ans;
}
let n = 2;
let k = 2;
let ans = bishop_placements(n, k);
document.write(ans);
</script> |
4
Time Complexity: O(n^2 * k), where n is the size of the chessboard and k is the number of bishops to be placed.
Space Complexity: O(n^2 * k), since we are using a 2D dp table of size n * 2 x k + 1 to store the values of the dynamic programming solution.