洛谷P1219 八皇后 (dfs+回溯法)

https://www.luogu.org/problem/P1219

题意:每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子,输出所有方案中的前三个方案

每一个方案中,都是从第一行开始搜,一行一行的搜,横坐标不会出现重复的情况,所以只需要标记纵坐标即可;从右上到左下的对角线及其平行线,会发现,横纵坐标之和相等;从左上到右下的对角线及其平行线,会发现,横纵坐标之差相等,(x-y)可能为负数,用x-y+n表示;

// luogu-judger-enable-o2
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <cstring>
#include <map>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long lll;
const int maxn = 200005;
const lll INF = 0x3f3f3f3f3f;
int ans[50],vis1[50],vis2[50],vis3[50],n,m;
void output()
{
    m++;
    if(m <= 3)//只输出前三种方案
    {
        for(int i=1; i<=n; i++)
        {
            cout << ans[i];
            if(i < n) cout << " ";
            else cout << endl;
        }
    }
}
void dfs(int i)
{
    if(i>n)
    {
        output();//当前的行数大于了n行 该方案满足要求 输出
    }
    else
    {
        for(int j = 1; j <= n; j++)//每一行对应的列数
        {
            if(!vis1[j]&&!vis2[i+j]&&!vis3[i-j+n])//纵坐标及两条对角线满足的话
            {
                ans[i] = j;
                vis1[j] = 1;
                vis2[i+j] = 1;
                vis3[i-j+n] = 1;//做上标记 表示当前方案正在使用
                dfs(i+1);//搜下一行
                vis1[j] = 0;
                vis2[i+j] = 0;
                vis3[i-j+n] = 0;//标记回来 下一种方案可以接着使用
            }
        }
    }
}
int main()
{
    cin >> n;
    dfs(1);//从第一行开始搜
    cout << m;
    return 0;
}
原文地址:https://www.cnblogs.com/LLLAIH/p/11293962.html