问题描述:
n皇后问题指在一个n*n的棋盘上放置n个皇后,使得这n个皇后两两均不在同一行、同一列、同意对角线上,求方案数。
思路
如果用组合数的方式,就有c(n,n*n)的枚举量,n过大时,时间复杂度将无法接受。换个思路就是,n * n就有n个行,n个列,想象n列皇后每个列分到一个行里,这样就是1-n的行的排列,而且绝对不会出现同一行,同一列会有两个皇后,只剩下考虑对角线就是。
全排列用递归来计算。
代码
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 100;
int n, P[maxn], hashTable[maxn] = {false};
int count = 0;
void generateP(int index);
void generateP1(int index);
int main()
{
scanf("%d", &n);
generateP1(1);
printf("%d\n", count);
return 0;
}
//朴素全排列
void generateP(int index)
{
if(index == n + 1)
{
bool flag = true;
for(int i = 1; i < n; i++)
{
for(int j = i + 1; j <= n; j++)
{
//判断对角线
if(abs(i - j) == abs(P[i] - P[j]))
{
flag = false;
}
}
}
if(flag)
{
count++;
}
return ;
}
for(int i = 1; i <= n; i++)
{
if(hashTable[i] == false)
{
P[index] = i;
hashTable[i] = true;
generateP(index + 1);
hashTable[i] = false;
}
}
}
//回溯法
void generateP1(int index)
{
if(index == n + 1)
{
count ++;
return ;
}
for(int x = 1; x <= n; x++)
{
if(hashTable[x] == false)
{
bool flag = true;
for(int pre = 1; pre < index; pre++)
{
//x是index列的皇后,这里判断之前的皇后会不会和接下来的x冲突
if(abs(index - pre) == abs(x - P[pre]))
{
flag = false;
break;
}
}
if(flag)
{
P[index] = x;
hashTable[x] = true;
generateP1(index + 1);
hashTable[x] = false;
}
}
}
}