代码:

#include<bits/stdc++.h>
using namespace std;

int n,a[50],total;
int b[100],c[100],d[100];//b,c,d分别代表列,主对角线,副对角线,初始值为0,当有一个皇后出现时,需要将其所占的列,主,副对角线标记为1

void dfs(int i)//这里i代表的是第i个皇后
{
    if(i>n)//i>n时说明已经有了一种解法
    {
        total++;
        if(total<=3)
        {
            for(int j=1;j<=n;j++)
            {
                printf("%d ",a[j]);
            }
            printf("\n");
        }
        return;
    }
    for(int j=1;j<=n;j++)
    {
        if(!b[j]&&!c[i+j]&&!d[i-j+n])//(i,j)所占列,主,副对角线都未被标记的情况下
        {
            a[i] = j;
            b[j] = 1;
            c[i+j] = 1;
            d[i-j+n] = 1;//打标记
            dfs(i+1);
            b[j] = 0;
            c[i+j] = 0;
            d[i-j+n] = 0;//回溯的时候,需要把标记去掉
        }
    }
}
int main()
{
    scanf("%d",&n);
    dfs(1);
    printf("%d",total);
    return 0;
}
  • 需要注意的几点性质(关于这个性质可以很容易画图得到):
    1.主对角线上所有点的坐标x+y相等(这里的主对角线表示的是左下到右上)
    2.副对角线上所有点的坐标x-y相等(副对角线表示左上到右下)
    3.代码中d[i-j+n],加n的原因是i-j会出现负数,而我们对其加任意大小的数不会改变她表示副对角线的唯一性,至于加n的原因是i-j最大的负数是1-n,所以我们只需要加n即可。