P1219 [USACO1.5] 八皇后 Checker Challenge
求求大家给个关注吧,你关注我我是一定会回关的!资瓷壶关!【狗头】一个如下的 6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。上面的布局可以用序列 2 4 6 1 3 5 来描述,第 i 个数字表示在第 i 行的相应位置有一个棋子,如下:行号 1 2 3 4 5 6列号 2 4 6 1 3 5这只是棋子放置的一个解
求求大家给个关注吧,你关注我我是一定会回关的!资瓷壶关!【狗头】
一个如下的 6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列 2 4 6 1 3 5 来描述,第 i 个数字表示在第 i 行的相应位置有一个棋子,如下:
行号 1 2 3 4 5 6
列号 2 4 6 1 3 5
这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 3 个解。最后一行是解的总个数。
输入格式
一行一个正整数 n,表示棋盘是 n×n 大小的。
输出格式
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
输入输出样例
输入 #1复制
6
输出 #1复制
2 4 6 1 3 5 3 6 2 5 1 4 4 1 5 2 6 3 4
说明/提示
【数据范围】
对于 100% 的数据,6≤n≤13。
--------------------------------------------------------------------------------------------------------------------------------
还是一个dfs题目,如果dfs不熟的人可以先阅读这几篇:
--------------------------------------------------------------------------------------------------------------------------------
前引
众所周知这件众所周知的事情众所周知,题目中和明确说每一行,每一列,每一个斜杠都只能放一个皇后,所以我们可以用到和P1605 迷宫(在上面)的一个visit数组来标记每一行,每一列,每一个斜杠有没有放过皇后。有就是true,没有就是false。
--------------------------------------------------------------------------------------------------------------------------------
思路
既然我们已经知道visit数组的用方法,题目也不难了。我们可以枚举每一种情况。
我们以行数为DFS遍历单位,每一行我们都遍历每一个元素是否符合要求,也就是行,列,斜杠的visit数组是否为false。如果有多种情况那么可能需要放多次皇后,但是切记传递完后要把放了皇后的位置改回原本的false,这样就不会影响下一次传递。(行不用visit数组,因为我们行为单位去遍历)。
这时候就有人要问了:列的visit数组的下标都很好理解,那斜杠的下标怎么写呢?其实要想求出左斜杠和右斜杠的下标,记住这两个公式:a-i+n和a+i。这个不用刻意去理解,只需要记住就好了,想知道公式其原因的同学举几个例子就知道了。
--------------------------------------------------------------------------------------------------------------------------------
详细见代码:
#include <bits/stdc++.h>
using namespace std;
bool c[55], z[55], f[55];
int p[55];
int n, s;
void d(int a){
if(a==n+1){
s++;
if(s<=3){
for(int i=1; i<=n; i++){
printf("%d ", p[i]);
}
printf("\n");
}
return ;
}
for(int i=1; i<=n; i++){
if(!c[i] && !z[a-i+n] && !f[a+i]){
p[a]=i;
c[i]=z[a-i+n]=f[a+i]=true;
d(a+1);
c[i]=z[a-i+n]=f[a+i]=false; //遍历完后记得修改回来!
}
}
}
int main(){
scanf("%d", &n);
d(1);
printf("%d", s);
return 0;
}
输出的方法我就不讲了,大家可以自己去理解。反正p数组是记录答案的,记录方法类似全排列问题。
完结撒花!!!
代码仅供借鉴!
有什么问题在评论区告诉我。
求关注!
一定互关!
本期就到这,欢迎大家对我提出问题,拜拜!!
更多推荐



所有评论(0)