题目大意:八皇后变成14皇后,加了不能放的区域。
参考题解
逐行放置皇后,首先排除每行有多个皇后互相排斥的情况
用二进制表示状态.1表示该点不能放(与其他位置的皇后排斥或初始状态就不能放).0表示该点可以放皇后
用map[]来存储初始状态,将'.'位 置为1
dfs保存四个参数:当前列的状态,从左上到右下对角线的状态,从右上到左下对角线的状态,当前为第几行
获取当前哪一位可以放置皇后:将四者取并集(即将四者进行或运算).得到的状态中为1的就可以放置皇后.
用树状数组中的lowbit()就可以得到从右向左的第一个1
将状态中的1减掉,继续找下一个1
更新"将是下一行的状态",由于对角线是斜着影响的,所以左上到右下对角线的状态需要左移一位,右上到左下对角线的状态需要右移一位.
- 知道当n个皇后都放下时候,ans++;
#include <iostream>
#include<stdio.h>
using namespace std;
int n,ans,End,map[20];
void dfs(int row,int ld,int rd,int d) { //row列,ld右斜 ,d行
if(d>n) { //if(row==End)
ans++;return;
}
int pos=End&(~(row|ld|rd|map[d])),p;
while(pos) {
p=pos&(-pos);//找到第一个非零位置。
pos-=p;
dfs(row+p,(ld+p)<<1,(rd+p)>>1,d+1);//ld+p右移,左斜线不能再用, rd+p右斜,d+1,下一行;
}
}
int main() {
char s[20];
int i,j,k;
scanf("%d\n",&n);
End=(1<<n)-1;
for(i=1; i<=n; i++) {
gets(s);
for(j=1; j<=n; j++)
map[i]=(s[j-1]=='.')+(map[i]<<1);
}
dfs(0,0,0,1);
printf("%d",ans);
return 0;
}