题目传送门
[USACO1.5] 八皇后 Checker Challenge
题目描述
一个如下的 6 × 6 6 \times 6 6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列 2 4 6 1 3 5 2\ 4\ 6\ 1\ 3\ 5 2 4 6 1 3 5 来描述,第 i i i 个数字表示在第 i i i 行的相应位置有一个棋子,如下:
行号 1 2 3 4 5 6 1\ 2\ 3\ 4\ 5\ 6 1 2 3 4 5 6
列号 2 4 6 1 3 5 2\ 4\ 6\ 1\ 3\ 5 2 4 6 1 3 5
这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
 并把它们以上面的序列方法输出,解按字典顺序排列。
 请输出前  
     
      
       
       
         3 
        
       
      
        3 
       
      
    3 个解。最后一行是解的总个数。
输入格式
一行一个正整数 n n n,表示棋盘是 n × n n \times n n×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 
        
       
         % 
        
       
      
        100\% 
       
      
    100% 的数据, 
     
      
       
       
         6 
        
       
         ≤ 
        
       
         n 
        
       
         ≤ 
        
       
         13 
        
       
      
        6 \le n \le 13 
       
      
    6≤n≤13。
题目翻译来自NOCOW。
USACO Training Section 1.5
思考:
注意到题目给我们的输出方式,是以行为顺序输出相应棋子的列号的。
 所以我们不难想到这道题需要以行号为搜索状态进行搜索。
 每一行只能放一个棋子,所以我们在每一行中只要直接枚举当前行棋子的列号就可以了。
 如何判断当前棋子是否能放呢?
 注意棋子能放的条件:每行每列每条对角线只能有一颗棋子。
 行号是我们搜索的状态,所以不用管,直接保证了每行只能有一颗棋子
 我们只需要用三个数组分别表示当前列,两条对角线棋子的放置情况就可以了。
 列好表示,直接用 
     
      
       
       
         L 
        
       
         [ 
        
       
         i 
        
       
         ] 
        
       
      
        L[i] 
       
      
    L[i]表示第i列是否有棋子就可以了。
 那么对角线呢?
 在这里我们就需要用到对角线的性质:
- 对于同一条左对角线上的点我们不难发现行和列的坐标和是一样的。
- 而右对角线响应的是行和列的坐标差是一样的。
利用这个性质我们分别用 Z [ i ] Z[i] Z[i]和 Y [ i ] Y[i] Y[i]去存储行列的和差情况即可。
#include<bits/stdc++.h>
using namespace std;
int Ans = 0;
int a[20];
int n;
int L[50],Z[50],Y[50];
void Work(){
	Ans++;
	if (Ans <= 3){
	    for (int i = 1; i < n; i++) printf("%d ",a[i]);
	    printf("%d\n",a[n]);
	}
}
void Dfs(int now){
	if (now == n+1) {Work();return;}
	for (int i = 1; i <= n; i++)
	  if (!L[i] && !Z[now-i+n] && !Y[now+i]){
	  	L[i] = 1; Z[now-i+n] = 1; Y[now+i] = 1;
	  	a[now] = i;
	  	Dfs(now+1);
	  	L[i] = 0; Z[now-i+n] = 0; Y[now+i] = 0;
	  }
}
int main(){
	scanf("%d",&n);
	Dfs(1);
	printf("%d",Ans);
}



















