标签:
时间限制:2000MS 内存限制:65535K
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
有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\n",cnt); 50 } 51 return 0; 52 }
标签:
原文地址:http://www.cnblogs.com/geek1116/p/5553536.html