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; }