P1219 [USACO1.5] 八皇后 Checker Challenge 题解
题目链接 https://www.luogu.com.cn/problem/P1219
[USACO1.5] 八皇后 Checker Challenge
题目描述
一个如下的 \(6 \times 6\) 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列 \(2\ 4\ 6\ 1\ 3\ 5\) 来描述,第 \(i\) 个数字表示在第 \(i\) 行的相应位置有一个棋子,如下:
行号 \(1\ 2\ 3\ 4\ 5\ 6\)
列号 \(2\ 4\ 6\ 1\ 3\ 5\)
这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 \(3\) 个解。最后一行是解的总个数。
输入格式
一行一个正整数 \(n\),表示棋盘是 \(n \times n\) 大小的。
输出格式
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
样例 #1
样例输入 #1
6
样例输出 #1
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4
提示
【数据范围】
对于 \(100\%\) 的数据,\(6 \le n \le 13\)。
题目翻译来自NOCOW。
USACO Training Section 1.5
思路描述
题意就是在\(n \times n\)的棋盘上每行、每列,每条对角线和两条主对角线的所有平行线,最多只有一个皇后。\(n\)的范围是\(6 \le n \le 13\),我们可以直接用\(DFS\)来搜索,用bool类型的数组来标记是否被占就行了,那这道题就是一道简单的深搜题。
\(dfs\)代码:
void dfs(int x) { //考虑第i行的皇后在哪一列。
if(x==n+1) { //终止条件就是超过棋盘的范围
ans++;
if(ans<=3) { //如果方案数超过3
for(int i=1; i<=n; i++)
cout<<a[i]<<' ';//输出前3个方案
cout<<endl;
}
return;
}
for(int i=1; i<=n; i++) {
if(b[i]==false&&c[x+i]==false&&d[x-i+n]==false) { //分别判断列,右上到左下对角线,左上到右下对角线是否有棋子
a[x]=i;//记录纵坐标
b[i]=true;//列被占
c[x+i]=true;//右上到左下对角线被占
d[x-i+n]=true;//左上到右下对角线被占
dfs(x+1);
b[i]=false;//将三个数组全部清空
c[x+i]=false;
d[x-i+n]=false;
}
}
}
主函数代码:
int main() {
cin>>n;
dfs(1);
cout<<ans<<endl;
return 0;
}//挺简单的就不用解释了
完整代码:
#include<iostream>
#include<cstring>
using namespace std;
int n;
int a[100];
bool b[100],c[100],d[100];
int ans;
void dfs(int x) {
if(x==n+1) {
ans++;
if(ans<=3) {
for(int i=1; i<=n; i++)
cout<<a[i]<<' ';
cout<<endl;
}
return;
}
for(int i=1; i<=n; i++) {
if(b[i]==false&&c[x+i]==false&&d[x-i+n]==false) {
a[x]=i;
b[i]=true;
c[x+i]=true;
d[x-i+n]=true;
dfs(x+1);
b[i]=false;
c[x+i]=false;
d[x-i+n]=false;
}
}
}
int main() {
cin>>n;
dfs(1);
cout<<ans<<endl;
return 0;
}
时间复杂度
因为n最大只有13所以不用担心时间复杂度;

浙公网安备 33010602011771号