给定棋盘的尺寸(N x M),确定覆盖棋盘所有正方形所需的最小皇后数量。女王可以沿着其行,列或对角线攻击任何正方形。
例子:
Input : N = 8, M = 8
Output : 5
Layout : Q X X X X X X X
X X Q X X X X X
X X X X Q X X X
X Q X X X X X X
X X X Q X X X X
X X X X X X X X
X X X X X X X X
X X X X X X X X
Input : N = 3, M = 5
Output : 2
Layout : Q X X X X
X X X X X
X X X Q X
本文试图以一种非常简单的方式解决该问题,而没有进行太多优化。
Step 1: Starting from any corner square of the board, find an ‘uncovered’ square (Uncovered square is a square which isn’t attacked by any of the queens already placed). If none found, goto Step 4.
Step 2: Place a Queen on this square and increment variable ‘count’ by 1.
Step 3: Repeat step 1.
Step 4: Now, you’ve got a layout where every square is covered. Therefore, the value of ‘count’ can be the answer. However, you might be able to do better, as there might exist a better layout with lesser number of queens. So, store this ‘count’ as the best value till now and proceed to find a better solution.
Step 5: Remove the last queen placed and place it in the next ‘uncovered’ cell.
Step 6: Proceed recursively and try out all the possible layouts. Finally, the one with the least number of queens is the answer.
为了更好地理解,请空运行以下代码。
// Java program to find minimum number of queens needed
// to cover a given chess board.
public class Backtracking {
// The chessboard is represented by a 2D array.
static boolean[][] board;
// N x M is the dimension of the chess board.
static int N, M;
// The minimum number of queens required.
// Initially, set to MAX_VAL.
static int minCount = Integer.MAX_VALUE;
static String layout; // Stores the best layout.
// Driver code
public static void main(String[] args)
{
N = 8;
M = 8;
board = new boolean[N][M];
placeQueen(0);
System.out.println(minCount);
System.out.println("\nLayout: \n" + layout);
}
// Finds minimum count of queens needed and places them.
static void placeQueen(int countSoFar)
{
int i, j;
if (countSoFar >= minCount)
// We've already obtained a solution with lesser or
// same number of queens. Hence, no need to proceed.
return;
// Checks if there exists any unattacked cells.
findUnattackedCell : {
for (i = 0; i < N; ++i)
for (j = 0; j < M; ++j)
if (!isAttacked(i, j))
// Square (i, j) is unattacked.
break findUnattackedCell;
// All squares all covered. Hence, this
// is the best solution till now.
minCount = countSoFar;
storeLayout();
return;
}
for (i = 0; i < N; ++i)
for (j = 0; j < M; ++j) {
if (!isAttacked(i, j)) {
// Square (i, j) is unattacked.
// Therefore, place a queen here.
board[i][j] = true;
// Increment 'count' and proceed recursively.
placeQueen(countSoFar + 1);
// Remove this queen and attempt to
// find a better solution.
board[i][j] = false;
}
}
}
// Returns 'true' if the square (row, col) is
// being attacked by at least one queen.
static boolean isAttacked(int row, int col)
{
int i, j;
// Check the 'col'th column for any queen.
for (i = 0; i < N; ++i)
if (board[i][col])
return true;
// Check the 'row'th row for any queen.
for (j = 0; j < M; ++j)
if (board[row][j])
return true;
// Check the diagonals for any queen.
for (i = 0; i < Math.min(N, M); ++i)
if (row - i >= 0 && col - i >= 0 &&
board[row - i][col - i])
return true;
else if (row - i >= 0 && col + i < M &&
board[row - i][col + i])
return true;
else if (row + i < N && col - i >= 0 &&
board[row + i][col - i])
return true;
else if (row + i < N && col + i < M &&
board[row + i][col + i])
return true;
// This square is unattacked. Hence return 'false'.
return false;
}
// Stores the current layout in 'layout'
// variable as String.
static void storeLayout()
{
StringBuilder sb = new StringBuilder();
for (boolean[] row : board) {
for (boolean cell : row)
sb.append(cell ? "Q " : "X ");
sb.append("\n");
}
layout = sb.toString();
}
}
5
Layout:
Q X X X X X X X
X X Q X X X X X
X X X X Q X X X
X Q X X X X X X
X X X Q X X X X
X X X X X X X X
X X X X X X X X
X X X X X X X X