@miorel关于回溯是完全正确的。只是为了好玩,我尝试使用简单的递归算法在 C/C++ 中解决这种蛮力,并进行了一个简单的优化:
我们知道,对于任何给定的问题大小 N,每个皇后都将位于单独的列中。所以我们甚至不尝试其他列。所以想法是这样的:
- 每个皇后都有自己的列,因此皇后 1 进入第 1 列,皇后 2 进入第 2 列,以此类推。
- 所以真正的目标是为每个皇后挑选一行。从第一个皇后开始,让我们依次尝试每一行。我们通过在可能的行中放置一个皇后来做到这一点,然后进行递归调用以放置第二个、第三个和第四个皇后。
在检查放置是否兼容时,我们只需要检查 a) 同一行是否有皇后 b) 是否有对角线皇后。
#include <stdlib.h>
#include <stdio.h>
int solveQueens(int queenIndex, int sz, int * positions) {
for (int i=0; i<sz; i++) {
int valid = 1;
for (int j=0; j<queenIndex; j++) {
int diff = queenIndex-j;
if (
(positions[j]==i)
|| (positions[j]+diff == i)
|| (positions[j]-diff == i)
) {
valid = 0;
break;
}
}
if (valid) {
positions[queenIndex]=i;
if (queenIndex < sz-1) {
// Recursive call
int res = solveQueens(queenIndex+1, sz, positions);
if (res)
return 1;
} else {
return 1;
}
}
}
return 0;
}
void printQueens(int sz, int * positions) {
for (int i=0; i<sz; i++) {
printf("%c%d ", (char)(i+(int)'A'), positions[i]+1);
}
}
void queens(int sz) {
int * positions = (int *)malloc(sizeof(int)*sz);
if (solveQueens(0, sz, positions)) {
printQueens(sz, positions);
} else {
printf("No solutions found\n");
}
free(positions);
}
int main() {
queens(24);
return 0;
}
我确信这不是最佳算法,但它在 24 板大小的板上工作时间不到 1 秒。