题目描述:
在国际象棋中规定:
皇后能在行、列、对角线上任意移动或攻击。
现在,我们把N个棋子被放置在棋盘上,使得每行、每列、每条对角线(包括两条主对角线的所有对角线)上有且只有一个棋子。
在已知N的情况下,你要计算出有多少种排列方式符合要求。
输入格式:
输入只有一行。
这一行只包括一个整数N,表示棋盘大小是N x N。
输出格式:
输出只有一行。
这一行只包括一个整数,即总共有多少种排列方式。
数据范围:
4≤N≤13。
样例输入:
6
样例输出:
4
问题分析:
此解法来自Matrix67的大牛的Blog,思路就是递归,只是判断时用了位运算。
参考程序:
1 #include<stdio.h>
2 int n,upperlim,sum=0;
3 int test(int row,int ld,int rd)/*row,ld,rd分别表示列、左下到右上的对角线、左上到右下的对角线*/
4 {
5 int pos,p;
6 if(row!=upperlim)
7 {
8 pos=upperlim&~(row|ld|rd);/*row、ld和rd中的1表示冲突位置,即该处不能再放皇后,~后表示可以放,pos表示所有可以放的位置。*/
9 while(pos!=0)/*当pos不等于0时,说明row,ld,rd中还有0,即还有可以放皇后的位置,为了求出所有解,必须依次遍历所有可放的位置*/
10 {
11 p=pos&(~pos+1);/*取出pos中最右边的那个1,即取出最右边可以放的位置*/
12 pos-=p;/*每走过一个点就要删掉它,否则就成死循环啦*/
13 test(row+p,(ld+p)<<1,(rd+p)>>1);/*递归试探此状态下其它棋子的位置,(ld+p)<<1 是因为由ld造成的占位在下一行要右移一下*/
14 }
15 }
16 else sum++;/*当pos=upperlim时,说明全部皇后已经放置好,所以把sum的值加1*/
17 }
18 int main()
19 {
20 scanf("%d",&n);
21 upperlim=(1<<n)-1;/*11111111*/
22 test(0,0,0);
23 printf("%d",sum);
24 return 0;
25 }
题目描述:
浙公网安备 33010602011771号