题目描述
利用回溯法计算 n*n 棋盘中摆放 n 个皇后的方案数
输入格式
第一行有一个整数 k,表示有 k 个 case,
接下来 2..k+1 行,每行有一个整数,表示 n*n 的棋盘 (0 < n <= 8)。
输出格式
输出共有 k 行
每行有一个整数,即 n*n 的摆放皇后的方案数
样例
input
2 8 8output
92 92
思路:网上找到了另一种回溯法,用二进制位来记录当前行可以走的格子,并可以推导出下一行可以走的格子。基本思想是:用col、m_diag、c_diag三个变量的最低n位记录当前行的列、主对角线、副对角线占用情况,1表示被占用,0表示可以走,三个变量或运算的结果是这行可以走的格子情况,并以此递推出下一行可用的格子。如果皇后太多的话,int类型的位数可能不够用,可以考虑使用bitset替代。具体代码如下:
#include <iostream>
using namespace std;
int lim, ans;
void queen(int col, int m_diag, int c_diag)//col,m_diag,c_diag每一位的1表示被占用,0表示可走
{
if(col == lim){//所有列都走完了
++ans;
return;
}
int pos = lim & ~(col | m_diag | c_diag);//求得所有可走的格子并用1表示
while(pos){//当前行仍有格子可以走
int cur = pos & (~pos + 1);//提取最低位的1(最右边可走的格子)
pos -= cur;//更新该格子为被占用
queen(col+cur, (m_diag+cur)>>1, (c_diag+cur)<<1);//递推下一行的占用情况
}
}
int main()
{
int k, n;
cin>>k;
for(int cas=0; cas<k; ++cas){
cin>>n;
ans = 0;
lim = 1;
lim = (lim<<n) - 1;//lim的低n位置1,表示某一行所有格子都不能走
queen(0, 0, 0);
cout<<ans<<endl;
}
return 0;
}