传送门:https://www.luogu.com.cn/problem/P1562
参考博客:https://blog.csdn.net/qq_40828060/article/details/79364577
这题一开始用普通dfs,超时。
看大佬用位运算,我也来试试。不同的是,我用0表示不可放置,1表示可放置,那么,在dfs的参数传递时有点麻烦
dfs函数中,p中的1,表示该行放置的位置,在进一步dfs时,考虑到对下一行的影响,~p才表示可放置的位置。
在同一列的角度,应当是当前列&~p:row&~p
在主对角线(left diagonal),应当是(当前状态&~p)>>1,再高位补1,注意此时补的1应当为(1<<N>>1)
在次对角线(right diagonal),应当是(当前状态&~p)<<1,再低位补1,此时补的1是真的1。
不得不说,这么做非常麻烦,还是可放置用0表示,不可放置用1表示方便写程序。
我倔强地debug了2个多小时才把位运算这里搞完。唉,太菜了。!!!
#include <stdio.h>
#include <stdlib.h>
int N;
int ans;
int map[15];
int allone;
void dfs(int i,int row,int ld,int rd);
int main(void) {
char ch[16];
int i,j;
scanf("%d\n",&N);
allone=(1<<N)-1;
for(i=0; i<N; i++) {
gets(ch);
for(j=0; j<N; j++) {
map[i]=(ch[j]== '*')+(map[i]<<1);
}
}
dfs(0,allone,allone,allone);
printf("%d",ans);
return 0;
}
void dfs(int i,int row,int ld,int rd) {
int pos,p;
if(i==N) {
ans++;
return;
}
pos=allone&(map[i]&row&ld&rd);
while(pos) {
p=pos&(-pos);
pos-=p;
dfs(i+1,row&~p,1+((ld&~p)<<1),(1<<N>>1)+((rd&~p)>>1));//左移低位补1,右移低位补0
}
}