#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MIN_DISTANCE 2

// 判断当前皇后放置是否合法，并且符合安全距离条件
int place(int x[], int j) {
    for (int i = 1; i < j; i++) {
        // 检查列冲突、对角线冲突以及最小安全距离
        if (x[i] == x[j] || abs(j - i) == abs(x[j] - x[i]) || 
            abs(x[j] - x[i]) < MIN_DISTANCE || abs(j - i) < MIN_DISTANCE) {
            return 0; // 不合法
        }
    }
    return 1; // 合法
}

// 非递归方式解 N 皇后问题
void nQNoRec(int x[], int n, int *foundSolution) {
    int j = 1; // j 表示当前放置第 j 个皇后
    for (int i = 1; i <= n; i++) 
        x[i] = 0; 
    while (j >= 1) {
        while (x[j] < n) {
            x[j] = x[j] + 1;
            if (place(x, j)) {
                j = j + 1;
                if (j > n) { // 到达叶子节点
                    *foundSolution = 1;
                    return; // 找到一个解即可返回
                }
            }
        }
        x[j] = 0; // 回溯时，恢复当前位置的状态
        j = j - 1; // 向上回溯
    }
}

// 递归方式解 N 皇后问题
void nQueenRec(int x[], int j, int n, int *foundSolution) {
    if (j > n) { // 搜索到叶子节点  
        *foundSolution = 1;
        return; // 找到一个解即可返回
    } else { // 尝试在第 j 行放置皇后 
        for (int i = 1; i <= n; i++) {
            x[j] = i;
            if (place(x, j)) 
                nQueenRec(x, j + 1, n, foundSolution);  
            if (*foundSolution) return; // 如果已经找到解，则提前退出
        }
    }
}

int main() { 
    
    for (int n = 1; n <= 100; n++) {
        int x[n + 1]; // 存储每行皇后的位置   
        int hasSolution = 0;

        printf("Testing n = %d:\n", n);
        
        // 使用非递归方式检查是否有解
        nQNoRec(x, n, &hasSolution);
        if (hasSolution) {
            printf("There is at least one solution for n = %d.\n", n);
        } else {
            printf("No solution found for n = %d.\n", n);
        }

        // 也可以使用递归方式进行验证（可选）
        // hasSolution = 0;
        // nQueenRec(x, 1, n, &hasSolution);
        // if (!hasSolution) {
        //     printf("No solution found for n = %d using recursive method.\n", n);
        // }

        printf("****************************\n");
    }

    return 0;
}