洛谷 P1219 八皇后 超级详细题解

洛谷 P1219 八皇后 超级详细题解_第1张图片
洛谷 P1219 八皇后 超级详细题解_第2张图片

很明显本题要用到深度搜索dfs, 每次搜索都从第一行开始

第一次先从第一行第一列, 若搜索成功满足条件:

1、本列没有其他数 vis1[i]==0
2、该数对应的 左上到右下的对角线 没有其他数——vis2[i - cur + n]==0 我们可以发现!每条对角线上的横纵坐标之差始终相等 但是有的可能出现负数的情况 因此这里我们加上n 至于(i - cur)还是(cur - i)都是可以的 前后保持一致即可
3、该数对应的 右上到左下的对角线 没有其他数——vis3[i + cur]==0 我们也可以发现!!每条对角线横纵坐标之和相等!

则向第二层进发——dfs(cur + 1)

注意!此处不能是++cur !! cur不能改变 因为每次的最初都是要从第一行开始的! 血的教训!!

这样一直向下搜索~~
如果顺利的话就一直向下知道最后一行这时cur == n + 1(这时一层一层向下递归导致的结果)——输出!
若到某一行没有满足条件的则进行回溯,返回上一行换一个重新开始

AC代码(含详细注释):

#include//万能头文件
using namespace std;
vector  vec;//使用vector(可以理解为动态的数组)
int n, ans = 0;//n为行列数  ans记录答案个数 
int vis1[100];//列  起一个标记作用   以便于看他对应的列是否已经有其他数了  
int vis2[100];//右斜  起一个标记作用   以便于看他对应的列是否已经有其他数了  
int vis3[100];左斜  起一个标记作用   以便于看他对应的列是否已经有其他数了  
void dfs(int cur)
{
    if(cur > n)//若所有都满足条件
    {
        ans++;
        if(ans <= 3)//输出前三个答案
        {
            for(int i = 0; i < n; i++)
            {
                cout << vec[i] << " ";//直接当成数组用的
            }
            cout << endl;
        }
    }

    for(int i = 1; i <= n; i++)//从第一列到最后一列挨个试
    {
        if(!vis1[i] && !vis2[i - cur + n] && !vis3[i + cur])//满足条件否??
        {
            vis1[i] = 1;//标记  这一列我先占上了!
            vis2[i - cur + n] = 1;//同理 
            vis3[i + cur] = 1;//同理

            vec.push_back(i);//将符合条件的列存入vector中
            dfs(cur + 1);//递归  下一层进发
            vec.pop_back();//回溯 

            vis1[i] = 0;//撤销标记
            vis2[i - cur + n] = 0;//撤销标记
            vis3[i + cur] = 0;//撤销标记
        }
    }
}

int main()
{
    cin >> n;
    dfs(1);
    cout << ans;
    return 0;
}

觉得还不错请点个赞再走吧~~ 笔芯!

你可能感兴趣的:(深度搜索dfs)