给定整数M,N和K ,任务是将K个骑士放置在M * N棋盘上,以使它们不会互相攻击。
预计骑士将被放置在板上的不同正方形上。骑士可以垂直移动两个正方形,水平移动一个正方形,水平移动两个正方形,垂直移动一个正方形。如果其中一个骑士可以单步到达对方,则骑士会互相攻击。有多种方法可以将K个骑士放置在M * N板上,有时也可以不放置它们。我们将列出所有可能的解决方案。
例子:
Input: M = 3, N = 3, K = 5
Output:
K A K
A K A
K A K
A K A
K K K
A K A
Total number of solutions : 2
Input: M = 5, N = 5, K = 13
Output:
K A K A K
A K A K A
K A K A K
A K A K A
K A K A K
Total number of solutions : 1
方法:可以使用回溯解决此问题。
想法是从第一排和第一列开始逐个放置骑士,然后向前移动到第一排和第二列,以使他们不会互相攻击。当一行结束时,我们移至下一行。在放置骑士之前,我们总是检查该方块是否安全,即它不是其他骑士的进攻位置。如果安全的话,我们将骑士放置在棋盘上并标记其进攻位置,否则我们将前进并检查是否有其他障碍物。遵循此步骤时,每次将新骑士插入板子时,我们都会制作一个新板子。这样做是因为,如果我们得到一个解决方案而我们需要其他解决方案,那么我们可以使用旧配置的骑士回溯到我们的旧主板,然后可以检查其他可能的解决方案。回溯的过程一直持续到我们获得所有可能的解决方案为止。
下面是上述方法的实现:
// 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