📌  相关文章
📜  放置K骑士,使他们不会互相攻击

📅  最后修改于: 2021-04-23 17:25:27             🧑  作者: Mango

给定整数M,N和K ,任务是将K个骑士放置在M * N棋盘上,以使它们不会互相攻击。
预计骑士将被放置在板上的不同正方形上。骑士可以垂直移动两个正方形,水平移动一个正方形,水平移动两个正方形,垂直移动一个正方形。如果其中一个骑士可以单步到达对方,则骑士会互相攻击。有多种方法可以将K个骑士放置在M * N板上,有时也可以不放置它们。我们将列出所有可能的解决方案。

例子:

方法:可以使用回溯解决此问题。
想法是从第一排和第一列开始逐个放置骑士,然后向前移动到第一排和第二列,以使他们不会互相攻击。当一行结束时,我们移至下一行。在放置骑士之前,我们总是检查该方块是否安全,即它不是其他骑士的进攻位置。如果安全的话,我们将骑士放置在棋盘上并标记其进攻位置,否则我们将前进并检查是否有其他障碍物。遵循此步骤时,每次将新骑士插入板子时,我们都会制作一个新板子。这样做是因为,如果我们得到一个解决方案而我们需要其他解决方案,那么我们可以使用旧配置的骑士回溯到我们的旧主板,然后可以检查其他可能的解决方案。回溯的过程一直持续到我们获得所有可能的解决方案为止。

下面是上述方法的实现:

// C++ implementation of the above approach
#include 
using namespace std;
  
/* m*n is the board dimension
k is the number of knights to be placed on board 
count is the number of possible solutions */
int m, n, k;
int count = 0;
  
/* This function is used to create an empty m*n board */
void makeBoard(char** board)
{
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            board[i][j] = '_';
        }
    }
}
  
/* This function displays our board */
void displayBoard(char** board)
{
    cout << endl
         << endl;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            cout << " " << board[i][j] << " ";
        }
        cout << endl;
    }
}
  
/* This function marks all the attacking
 position of a knight placed at board[i][j]
 position */
void attack(int i, int j, char a,
            char** board)
{
  
    /* conditions to ensure that the 
       block to be checked is inside the board */
    if ((i + 2) < m && (j - 1) >= 0) {
        board[i + 2][j - 1] = a;
    }
    if ((i - 2) >= 0 && (j - 1) >= 0) {
        board[i - 2][j - 1] = a;
    }
    if ((i + 2) < m && (j + 1) < n) {
        board[i + 2][j + 1] = a;
    }
    if ((i - 2) >= 0 && (j + 1) < n) {
        board[i - 2][j + 1] = a;
    }
    if ((i + 1) < m && (j + 2) < n) {
        board[i + 1][j + 2] = a;
    }
    if ((i - 1) >= 0 && (j + 2) < n) {
        board[i - 1][j + 2] = a;
    }
    if ((i + 1) < m && (j - 2) >= 0) {
        board[i + 1][j - 2] = a;
    }
    if ((i - 1) >= 0 && (j - 2) >= 0) {
        board[i - 1][j - 2] = a;
    }
}
  
/* If the position is empty,
   place the knight */
bool canPlace(int i, int j, char** board)
{
    if (board[i][j] == '_')
        return true;
    else
        return false;
}
  
/* Place the knight at [i][j] position
   on board */
void place(int i, int j, char k, char a,
           char** board, char** new_board)
{
  
    /* Copy the configurations of
     old board to new board */
    for (int y = 0; y < m; y++) {
        for (int z = 0; z < n; z++) {
            new_board[y][z] = board[y][z];
        }
    }
  
    /* Place the knight at [i][j]
    position on new board */
    new_board[i][j] = k;
  
    /* Mark all the attacking positions
    of newly placed knight on the new board */
    attack(i, j, a, new_board);
}
  
/* Function for placing knights on board
   such that they don't attack each other */
void kkn(int k, int sti, int stj, char** board)
{
  
    /* If there are no knights left to be placed,
     display the board and increment the count */
    if (k == 0) {
        displayBoard(board);
        count++;
    }
    else {
  
        /* Loop for checking all the 
       positions on m*n board */
        for (int i = sti; i < m; i++) {
            for (int j = stj; j < n; j++) {
  
                /* Is it possible to place knight at 
           [i][j] position on board? */
                if (canPlace(i, j, board)) {
  
                    /* Create a a new board and place the 
                      new knight on it */
                    char** new_board = new char*[m];
                    for (int x = 0; x < m; x++) {
                        new_board[x] = new char[n];
                    }
                    place(i, j, 'K', 'A', board, new_board);
  
                    /* Call the function recursively for
                      (k-1) leftover knights */
                    kkn(k - 1, i, j, new_board);
  
                    /* Delete the new board 
                    to free up the memory */
                    for (int x = 0; x < m; x++) {
                        delete[] new_board[x];
                    }
                    delete[] new_board;
                }
            }
            stj = 0;
        }
    }
}
  
// Driver code
int main()
{
    m = 4, n = 3, k = 6;
  
    /* Creation of a m*n board */
    char** board = new char*[m];
    for (int i = 0; i < m; i++) {
        board[i] = new char[n];
    }
  
    /* Make all the places are empty */
    makeBoard(board);
  
    kkn(k, 0, 0, board);
  
    cout << endl
         << "Total number of solutions : "
         << count;
    return 0;
}
输出:
K  K  K 
 A  A  A 
 A  A  A 
 K  K  K 

 K  A  K 
 A  K  A 
 K  A  K 
 A  K  A 

 A  K  A 
 K  A  K 
 A  K  A 
 K  A  K 

Total number of solutions : 3