18124 N皇后问题

18124 N皇后问题

时间限制:2000MS  内存限制:65535K
提交次数:0 通过次数:0

题型: 编程题   语言: G++;GCC;VC

 

Description

有N*N的国际象棋棋盘,要求在上面放N个皇后,要求任意两个皇后不会互杀,有多少种不同的放法?




输入格式

每一个数为T,代表CASE的数量,T<=13
此后,每行一个数N(13>=N>0)



输出格式

每一个CASE,输出对应答案



 

输入样例

2
4
5



 

输出样例

2
10



 

作者

 admin

  SCAU-N皇后问题—回溯。输入n,求出在n*n的棋盘上放置n个皇后可以有多少种解;就是一个八皇后问题,而且题目的n也非常的小,时间还给了2000ms,就算暴力回溯O(n^2)的复杂度都可以过。但这里介绍一个优化上的技巧。    皇后可以攻击到同行同列和两条对角线上的棋子,,那么肯定是一行行的放置,一行和一列都是只能放置一个棋子的。  在判断同列的时候,开一个row[MAXN+5]的数组来标记哪些列放置了皇后。  对于两个对角线;要判断是否已放有棋子,就只要再开个二维的数组diagonal[2][MAXN*2+5];   其中,y-x是主对角线,y+x是副对角线。 但y-x可能为负数,所以要写成y-x+n; 在判断到当前cur行上的位置j可以放置的话,就把diagonal[0][cur-j+n]和diagonal[1][cur+j]都标记为1 以此表示该条对角线上已经放置有棋子了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cctype>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <set>
 9 #include <map>
10 #include <queue>
11 #include <stack>
12 #include <utility>
13 #include <vector>
14 #define ll long long
15 #define inf 0x3f3f3f3f
16 using namespace std;
17 
18 int row[20],diagonal[2][30];//标记列和两条对角线的数组
19 int cnt,n;
20 void dfs(int cur)
21 {
22     if(cur==n+1) //到达递归边界
23     {
24         cnt++;
25         return;
26     }
27     for(int i=1;i<=n;i++)
28     {     //判断列上、两条对角线上是否已有棋子
29         if(!row[i]&&!diagonal[0][cur+i]&&!diagonal[1][cur-i+n])
30         {
31             row[i]=diagonal[0][cur+i]=diagonal[1][cur-i+n]=1;
32             dfs(cur+1);
33             row[i]=diagonal[0][cur+i]=diagonal[1][cur-i+n]=0;
34         }
35     }
36 }
37 int main()
38 {
39     //freopen("input.txt","r",stdin);
40     memset(row,0,sizeof(row));
41     memset(diagonal,0,sizeof(diagonal));
42     int t;
43     scanf("%d",&t);
44     while(t--)
45     {
46         scanf("%d",&n);
47         cnt=0;
48         dfs(1);
49         printf("%d
",cnt);
50     }
51     return 0;
52 }
原文地址:https://www.cnblogs.com/geek1116/p/5553536.html