问题描述
在一个 N X N 的国际象棋棋盘上,放置 N 个皇后,使得任何两个皇后之间都不能互相攻击。皇后在国际象棋中能够水平、垂直以及对角线方向上攻击其他棋子,因此放置的 N 个皇后必须满足:在同一行、同一列以及同一条对角线上不能有两个皇后。
1. 问题理解:
• 输入:一个整数 N,代表棋盘大小和皇后数量。
• 输出:所有满足条件的皇后放置方案,或方案数量。
代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define N 5 // 可以更改 N 的值来解决不同大小的皇后问题
int count = 0;
void printBoard(int board[N][N]);
// 函数来检查是否可以在 board[row][col] 放置皇后
int isSafe(int board[N][N], int row, int col) {
int i, j;
// 检查同一列
for (i = 0; i < row; i++)
if (board[i][col] == 1)
return 0;
// 检查左上对角线
for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
if (board[i][j] == 1)
return 0;
// 检查右上对角线
for (i = row, j = col; i >= 0 && j < N; i--, j++)
if (board[i][j] == 1)
return 0;
/*
举例:最开始row=0 由solveNQUtil函数可知:
board[0][0]可以放皇后 然后solveNQUtil(board, row + 1, solutions)递归
此时row=1 ,进入新的solveNQUtil函数,for循环中col=0开始++ 若borad[0][0]=1 同一列不可以放皇后即board[1][0]不可以放皇后
col+1=1,又因为board[1][1]=1所以board[1][1]不可以放皇后....
*/
return 1;
}
// 函数来解决 N 皇后问题
void solveNQUtil(int board[N][N], int row, int& solutions) {
// 如果所有皇后都放置完成
if (row >= N) {
solutions++;
printBoard(board);
return; //程序结束
}
// 在当前行尝试放置皇后并递归地放置剩下的皇后
for (int col = 0; col < N; col++) {
// 检查放置皇后的位置是否安全
if (isSafe(board, row, col)) {
board[row][col] = 1; // 放置皇后
solveNQUtil(board, row + 1, solutions); // 递归放置下一个皇后
board[row][col] = 0; // 回溯 把皇后位置重新变为0
}
}
}
// 打印棋盘函数
void printBoard(int board[N][N]) {
printf("Solution %d:\n", ++count);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
printf("%d ", board[i][j]);
printf("\n");
}
printf("\n");
}
// 用于解决 N 皇后问题的主函数
void solveNQ() {
int board[N][N] = { 0 }; // 初始化棋盘
int solutions = 0;
solveNQUtil(board, 0, solutions);
printf("Total number of solutions are %d\n", solutions);
}
// 主函数
int main() {
solveNQ();
return 0;
}
运行结果: