51. N 皇后

题目描述

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

示例

示例 1:
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2:
输入:n = 1
输出:[["Q"]]

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/n-…

实现

/*
 * 下面情况不要使用memset()函数直接初始化二级指针,memset只能对连续的内存初始化,二级指针分别malloc,两次malloc的地址可能不连续
 */
bool isValid(int *visited, int row, int col)
{
    // 依次遍历当前行row的之前所有行
    for (int i = 0; i < row; i++) {
        /* 
         * visited[i]  表示第i行的第visited[i]列有皇后
         *
         * visited[i] == col 表示col这一列上有其他皇后
         * row + col == visited[i] + i 表示右上角有其他皇后 画图显示,对于次对角线 row+col的值都是相同的,所以对于右上角i(row) + visited[i](col)与当前row+col相等
         * row - col == i - visited[i] 表示左上角有其他皇后 画图显示,对于主对角线 row-col的值都是相同的,所以对于左上角i(row) - visited[i](col)与当前row-col相等
         */
        if (visited[i] == col || row + col == visited[i] + i || row - col == i - visited[i]) {
            // 出现皇后相互冲突,返回false
            return false;
        }
    }
    // 未出现皇后互相冲突,返回true
    return true;
}

void backtracking(int n, int *returnSize, int **returnColumnSizes, int row, char ***res, int *visited)
{
    if (row == n) {    // 遍历到了最后一行,找到的N皇后的一个解,保存
        res[*returnSize] = (char**)malloc(sizeof(char*) * n);    // 最多n个解
        memset(res[*returnSize], 0, sizeof(char*) * n);

        // 每个解都是一个二维数组
        for (int i = 0; i < n; i++) {
            res[*returnSize][i] = (char*)malloc(sizeof(char) * (n + 1));    // 每一个解的行
            memset(res[*returnSize][i], '.', sizeof(char) * n);
            res[*returnSize][i][n] = 0;
            res[*returnSize][i][visited[i]] = 'Q';
        }
        (*returnSize)++;
        return;
    }

    // 还未到达决策树底层,对row行的每一列遍历,搜索合适的位置放置皇后
    for (int i = 0; i < n; i++) {
        // 判断第row行第i列上是否会出现皇后冲突
        if (!isValid(visited, row, i)) {
            // 发生冲突,跳过此列,继续查找下一列
            continue;
        }
        visited[row] = i;    // 第row行有效的皇后为第i列
        backtracking(n, returnSize, returnColumnSizes, row + 1, res, visited);
        visited[row] = -1;   // 回溯
    }
}

char ***solveNQueens(int n, int *returnSize, int **returnColumnSizes)
{
    *returnSize = 0;
    int *visited = (int*)malloc(sizeof(int) * n);    // 保存每层存放皇后的列下标,如visited[0]=1,第0行第1列放皇后
    memset(visited, -1, sizeof(int) * n);

    char ***res = (char***)malloc(sizeof(char**) * n * n * n);   // 结果数组
    backtracking(n, returnSize, returnColumnSizes, 0, res, visited);      // 0表示当前的行数,从第0行开始
    *returnColumnSizes = (int*)malloc(sizeof(int) * (*returnSize));
    for (int i = 0; i < (*returnSize); i++) {
        (*returnColumnSizes)[i] = n;
    }
    /*
    printf("the number of res is %d\n", *returnSize);
    for (int i = 0; i < (*returnSize); i++) {
        printf("\n");
        for (int j = 0; j < n; j++) {
            printf("; ");
            for (int x = 0; x < n; x++) {
                printf("%c ", res[i][j][x]);
            }
        }
    }
    */
    return res;
}
复制代码
分类:
后端
标签: