📌  相关文章
📜  在 N×N 棋盘上放置 K 个主教的方法,以便没有两个攻击

📅  最后修改于: 2021-09-17 06:59:55             🧑  作者: Mango

给定两个整数NK ,任务是找到将K 个象放在N × N棋盘上的方法的数量,以便没有两个象互相攻击。

例子:

方法:这个问题可以用动态规划解决。

  • dp[i][j]表示将j 个主教放置在索引为i 的对角线上的方法数量,这些对角线的颜色与对角线i相同。然后i = 1…2N-1j = 0…K
  • 我们可以仅使用dp[i-2] 的值来计算dp[i][j] (我们减去 2,因为我们只考虑与 i 颜色相同的对角线)。有两种方法可以获得dp[i][j] 。要么我们将所有j 个主教放在之前的对角线上:那么有dp[i-2][j]种方法可以实现这一点。或者我们在对角线i上放置一个象,在之前的对角线上放置j-1 个象。这样做的方法的数量等于对角线i – (j – 1) 中的方格数,因为放置在先前对角线上的j-1 个主教中的每一个都将阻挡当前对角线上的一个方格。
  • 基本情况很简单: dp[i][0] = 1, dp[1][1] = 1
  • 一旦我们计算了dp[i][j] 的所有值,可以得到如下答案:考虑所有可能的放置在黑色对角线上的象数i=0…K ,以及相应的白色对角线Ki上的象数。放置在黑白对角线上的主教从不互相攻击,所以放置可以独立完成。最后一条黑色对角线的索引是2N-1 ,最后一条白色对角线的索引是2N-2 。对于每个i,我们将dp[2N-1][i] * dp[2N-2][Ki] 添加到答案中。

下面是上述方法的实现:

C++
// CPP implementation of the approach
#include
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
// 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);
    }
}


Python3
# 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#
// 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
 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
?>


Javascript


输出:
4

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程