题目描述
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;
}
复制代码