题目描述
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
思路
- DFS+回溯法求出所有可能
- 判断最终棋盘状态是否是合法
- 合法棋盘状态就输出
源码
leetcode上的C语言输出没看懂什么意思,只给出打印出结果的代码
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#define NULL_PTR (0)
#define TRUE (1)
#define FALSE (0)
#define SUCCESS (0)
#define FAIL (1)
#define MAX_N_QUEENS_ANS (10000)
char **g_map = NULL_PTR;
int g_diagFlag;
int g_dirt[4][2] =
{
{ 1, -1 },
{ -1, 1 },
{ -1, -1 },
{ 1, 1 },
};
int g_ansIndex;
/* 动态申请地图大小 */
void InitMap(int n)
{
int i;
int j;
if (g_map != NULL_PTR) {
return;
}
g_map = (char**)malloc(sizeof(char*) * n);
for (i = 0; i < n; i++) {
g_map[i] = (char*)malloc(sizeof(char) * n);
}
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
g_map[i][j] = '.';
}
}
}
/*销毁动态申请的地图*/
void DestoryMap(int n)
{
int i;
for (i = 0; i < n; i++) {
free(g_map[i]);
g_map[i] = NULL_PTR;
}
free(g_map);
g_map = NULL_PTR;
}
/*打印地图*/
void PrintMap(int n)
{
int i;
int j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%c ", g_map[i][j]);
}
printf("\n");
}
printf("\n");
}
/* 判断行 */
int IsValidRowConfig(int n, int row, int col)
{
int i;
for (i = 0; i < n; i++) {
if (i == col) {
continue;
}
if (g_map[row][i] == 'Q') {
return FALSE;
}
}
return TRUE;
}
/* 判断列 */
int IsValidColConfig(int n, int row, int col)
{
int i;
for (i = 0; i < n; i++) {
if (i == row) {
continue;
}
if (g_map[i][col] == 'Q') {
return FALSE;
}
}
return TRUE;
}
int IsValidPos(int n, int row, int col)
{
if ((row >= 0)&&(row < n)&& (col >= 0) && (col < n)) {
return TRUE;
}
return FALSE;
}
/* 判断对角线 */
void IsValidOneDiagConfig(int n, int row, int col, int dir)
{
int tmpRow;
int tmpCol;
if (IsValidPos(n, row, col) == FALSE) {
return;
}
if (g_map[row][col] == 'Q') {
g_diagFlag = TRUE;
return;
}
if (g_diagFlag == TRUE) {
return;
}
tmpRow = row + g_dirt[dir][0];
tmpCol = col + g_dirt[dir][1];
IsValidOneDiagConfig(n, tmpRow, tmpCol, dir);
}
int IsValidDiagConfig(int n, int row, int col)
{
int dir;
int tmpRow;
int tmpCol;
for (dir = 0; dir < 4; dir++) {
g_diagFlag = FALSE;
tmpRow = row + g_dirt[dir][0];
tmpCol = col + g_dirt[dir][1];
IsValidOneDiagConfig(n, tmpRow, tmpCol, dir);
if (g_diagFlag == TRUE) {
return FALSE;
}
}
return TRUE;
}
/*判断当前棋盘状态是否合法:任意两个皇后不在同一行,同一列,同一对角线*/
int IsValidConfig(int n)
{
int i;
int j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
if (g_map[i][j] == 'Q') {
/* 找到一个皇后,判断该皇后和其他皇后之间位置是否合法 */
if (IsValidRowConfig(n, i, j) == FALSE) {
return FALSE;
}
if (IsValidColConfig(n, i, j) == FALSE) {
return FALSE;
}
if (IsValidDiagConfig(n, i, j) == FALSE) {
return FALSE;
}
}
}
}
return TRUE;
}
/*
使用DFS求解N皇后问题
1. step表示遍历的深度,每一行放一个皇后,step==n时遍历结束
2. n表示皇后个数
3. 放皇后时需要考虑不能和其他皇后在同一行,同一列,同一对角线
*/
void DfsGetNQueen(int step, int n)
{
int i;
if (IsValidConfig(n) == FALSE) {
return;
}
if (step == n) {
PrintMap(n);
g_ansIndex++;
return;
}
for (i = 0; i < n; i++) {
g_map[step][i] = 'Q';
DfsGetNQueen(step + 1, n);
g_map[step][i] = '.';
}
}
int main()
{
int n = 4;
int step = 0;
InitMap(n);
//PrintMap(n);
g_ansIndex = 0;
DfsGetNQueen(step, n);
printf("total solution = %d\n", g_ansIndex);
DestoryMap(n);
return 0;
}