蓝桥杯 基础训练 2n皇后

  数月前做的2N皇后基本看书敲代码的,然后发现当时的代码不对,正好做到算法提高的8皇后·改,顺便把以前的代码顺带改了下,题目如下:

问题描述
  给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
  输入的第一行为一个整数n,表示棋盘的大小。
  接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
  输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
0
---------分割线---------
  书上的回溯法写起来未免比较麻烦,《算法竞赛入门经典》中就对N后问题有个方便的写法,就是用2维数组vis[3][2n]来判断当前是否可放皇后,第一行代表当前列是否已放过,第2、3行代表当前位置的斜线是否已放过;至于此题是黑白两色皇后,把所有单色皇后可行方案放在2维数组里,然后2个for循环判断两个方案是否有共同使用的位置,若无,则方案数+1,具体可见代码:
 1 #include<stdio.h>
 2 int a[8][8];
 3 int vis[3][20];
 4 int b[8];
 5 int c[100][8];
 6 int n;
 7 int count=0;
 8 void dfs(int cur)
 9 {
10     int i;
11     if(cur==n)
12     {
13         for(i=0;i<n;i++)
14             c[count][i]=b[i];
15         count++;
16     }
17     else for(i=0;i<n;i++)
18     {
19         if(a[cur][i]&&!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n])
20         {
21             b[cur]=i;
22             vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1;
23             dfs(cur+1);
24             vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;
25         }
26     }
27 }
28 int main()
29 {
30     int i,j,k,number=0,flag;
31     scanf("%d",&n);
32     for(i=0;i<n;i++)
33         for(j=0;j<n;j++)
34             scanf("%d",&a[i][j]);
35     dfs(0);
36     for(i=0;i<count;i++)
37     {
38         for(j=i+1;j<count;j++)
39         {
40             flag=1;
41             for(k=0;k<n;k++)
42             {
43                 if(c[i][k]==c[j][k])
44                 {
45                     flag=0;
46                     break;
47                 }
48             }
49             if(flag)
50                 number++;
51         }
52     }
53     printf("%d",number*2);
54     return 0;
55 }
原文地址:https://www.cnblogs.com/search-the-universe/p/last_month_3.html