P1219 [USACO1.5]八皇后 Checker Challenge

共对角线,行+列相同,或者行-列相同

dfs的典型例题

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

上面的布局可以用序列 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。

代码

#include 
int n,cnt=0,a[20];
int vis[20]={
     0},diagnol[50]={
     0},diagnor[50]={
     0};
void dfs(int k);
void output();
int main()
{
     
    scanf("%d",&n);
    dfs(1);
    printf("%d\n",cnt);
    return 0;
}
void dfs(int k)
{
     
    int i;
    for(i=1;i<=n;i++)
    if(!vis[i]&&!diagnol[k+i]&&!diagnor[k-i+12])//vis,不能同列。diagnol[i+k],若为1,则该棋子的位置与之前某棋子共/对角线
    {
     //对于\对角线,行-列可能为负,最小-12,故+12
        a[k]=i;
        vis[i]=1;
        diagnol[k+i]=1;
        diagnor[k-i+12]=1;
        if(k==n)output();
        else dfs(k+1);
        vis[i]=0;//回溯
        diagnol[k+i]=0;
        diagnor[k-i+12]=0;
    }
}
void output()
{
     
    cnt++;
    if(cnt<4){
     
    int i;
    printf("%d",a[1]);
    for(i=2;i<=n;i++)
        printf(" %d",a[i]);
    printf("\n");}
}

`

你可能感兴趣的:(P1219 [USACO1.5]八皇后 Checker Challenge)