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>
Output:
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.

