N 皇后问题 (DFS)

【题目描述】 N皇后问题
世界历史上曾经出现一个伟大的罗马共和时期,处于权力平衡的目的,当时的政治理论家波利比奥斯指出:“事涉每个人的权利,绝不应该让任何权利大的压过其它力量,使他人无法立足于平等条件与之抗辩的地步。”这类似著名的N皇后问题,即在NXN格的国际象棋上摆放N个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,请问有多少中摆法,并将每种摆法打印出来。图1所示即是摆法的一种。

在这里插入图片描述

问题简述: 输入棋盘n,输出摆放的方式有多少种。
问题分析: 通过dfs来搜索每个棋盘,这里存放已经放置的棋子用一维数组, arr[i]=j表示第i行第j列已放置一个棋子,这样可以省空间并且不用检查同行的棋子。斜直线用abs(x1-x2)是否等于abs(y1-y2)来判断即可。
由于是菜鸡,所以写的算法也只是普通的回溯,以后变强了会回来补优化的~
代码及注释如下:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#include<bitset>
#include<utility>
#include<functional>
#include<iomanip>
#include<sstream>
#include<ctime>
using namespace std;

const int N=105;

int arr[N];//arr[i]=j表示第i行第j列有一个皇后
//(这样存数据就不用检查同行是否有皇后,且省空间)
long long ans=0;//方案数
int n;//棋盘大小

bool check(int x,int y)//检查第x行第y列是否能放皇后
{
    for(int i=1;i<x;i++)//检查x行以前
    {
        if(arr[i]==y||abs(arr[i]-y)==abs(i-x))//如果发现同列有皇后或者同斜线有皇后,返回0(abs为取绝对值)
            return 0;
    }
    return 1;
}

void dfs(int x,int k)//第x行,已经放了k个棋子
{
    if(k==n)//如果已经摆放的皇后达到n个
    {
        ans++;
        return;
    }
    for(int i=1;i<=n;i++)//从每行的第一列开始循环查找
    {
        if(check(x,i))//如果可以放
        {
            arr[x]=i;//存储
            dfs(x+1,k+1);//搜索下一列
            arr[x]=0;//回溯清空
        }
    }
    return;
}

int main()
{
    while(cin>>n)
    {
        ans=0;
        memset(arr,0,sizeof(arr));
        dfs(1,0);
        cout<<ans<<endl<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44012745/article/details/88703269