N皇后变形题 https://www.acwing.com/problem/content/1434/
传统做法会在n=13时TL,学习了一下位运算。
传统回溯方法
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
using namespace std;
int a[15];
int num;
int n;
bool check(int x,int k)
{
for(int i=1;i<x;i++)
{
if(a[i]==k||abs(a[i]-k)==abs(x-i)) return false;
}
return true;
}
void dfs(int x)
{
if(x==n+1)
{
num++;
if(num<=3)
{
for(int i=1;i<=n;i++) cout<<a[i]<<' ';
cout<<endl;
}
return;
}
int i;
for(i=1;i<=n;i++)
{
if(check(x,i))
{
a[x] = i;
dfs(x+1);
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
a[1] = i;
dfs(2);
}
cout<<num<<endl;
return 0;
}
位运算方法
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int n,limit,num;
int a[15],k=1;
void dfs(int row,int ld,int rd)//行,左对角线,右对角线
{
if(row!=limit)
{
int pos = limit&(~(row|ld|rd));
while(pos)//每一个可以摆的位置,都要做一次
{
int p = pos&-pos;//lowbit操作
pos = pos-p;
if(num<3)
{
int t=p,num=1;
while(t!=1)
{
num++;
t>>=1;
}
a[k++] = num;
}
//(left | p)<< 1 是因为这一行由左对角线造成的禁止位在下一行要右移一下;right同理
dfs(row|p,(ld|p)<<1,(rd|p)>>1);
if(num<3) k--;
}
}
else//每一行都能放置棋子
{
if (num < 3) {
for (int i = 1; i <= n; i++) {
cout << a[i] << " ";
}
cout << endl;
}
num++;
}
}
int main()
{
cin>>n;
limit = (1<<n)-1;
dfs(0,0,0);
cout<<num<<endl;
return 0;
}