You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hello-algo/zh-hant/codes/c/chapter_backtracking/n_queens.c

96 lines
3.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* File : n_queens.c
* Created Time: 2023-09-25
* Author : lucas (superrat6@gmail.com)
*/
#include "../utils/common.h"
#define MAX_SIZE 100
/* 回溯演算法n 皇后 */
void backtrack(int row, int n, char state[MAX_SIZE][MAX_SIZE], char ***res, int *resSize, bool cols[MAX_SIZE],
bool diags1[2 * MAX_SIZE - 1], bool diags2[2 * MAX_SIZE - 1]) {
// 當放置完所有行時,記錄解
if (row == n) {
res[*resSize] = (char **)malloc(sizeof(char *) * n);
for (int i = 0; i < n; ++i) {
res[*resSize][i] = (char *)malloc(sizeof(char) * (n + 1));
strcpy(res[*resSize][i], state[i]);
}
(*resSize)++;
return;
}
// 走訪所有列
for (int col = 0; col < n; col++) {
// 計算該格子對應的主對角線和次對角線
int diag1 = row - col + n - 1;
int diag2 = row + col;
// 剪枝:不允許該格子所在列、主對角線、次對角線上存在皇后
if (!cols[col] && !diags1[diag1] && !diags2[diag2]) {
// 嘗試:將皇后放置在該格子
state[row][col] = 'Q';
cols[col] = diags1[diag1] = diags2[diag2] = true;
// 放置下一行
backtrack(row + 1, n, state, res, resSize, cols, diags1, diags2);
// 回退:將該格子恢復為空位
state[row][col] = '#';
cols[col] = diags1[diag1] = diags2[diag2] = false;
}
}
}
/* 求解 n 皇后 */
char ***nQueens(int n, int *returnSize) {
char state[MAX_SIZE][MAX_SIZE];
// 初始化 n*n 大小的棋盤,其中 'Q' 代表皇后,'#' 代表空位
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
state[i][j] = '#';
}
state[i][n] = '\0';
}
bool cols[MAX_SIZE] = {false}; // 記錄列是否有皇后
bool diags1[2 * MAX_SIZE - 1] = {false}; // 記錄主對角線上是否有皇后
bool diags2[2 * MAX_SIZE - 1] = {false}; // 記錄次對角線上是否有皇后
char ***res = (char ***)malloc(sizeof(char **) * MAX_SIZE);
*returnSize = 0;
backtrack(0, n, state, res, returnSize, cols, diags1, diags2);
return res;
}
/* Driver Code */
int main() {
int n = 4;
int returnSize;
char ***res = nQueens(n, &returnSize);
printf("輸入棋盤長寬為%d\n", n);
printf("皇后放置方案共有 %d 種\n", returnSize);
for (int i = 0; i < returnSize; ++i) {
for (int j = 0; j < n; ++j) {
printf("[");
for (int k = 0; res[i][j][k] != '\0'; ++k) {
printf("%c", res[i][j][k]);
if (res[i][j][k + 1] != '\0') {
printf(", ");
}
}
printf("]\n");
}
printf("---------------------\n");
}
// 釋放記憶體
for (int i = 0; i < returnSize; ++i) {
for (int j = 0; j < n; ++j) {
free(res[i][j]);
}
free(res[i]);
}
free(res);
return 0;
}