P1562 还是N皇后
考察:状压dp
时隔多年的复习233,还是做出来了
思路:
参考正常版的八皇后.我们需要标记左斜线,右斜线,已放棋子的列.在正常版我们是用数组记录,这里用状压dp可以用二进制位记录.所以三个变量now标记列,left是左斜线,right是右斜线.回溯不同于正常的dfs,正常的八皇后是用for循环枚举多种可能.这里用while.for循环枚举位数应该也可.
注意: left和right更新是需要先合并所选列在集体向左/右移.
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 using namespace std; 6 const int N = 15; 7 int mp[N],ans,n; 8 char tmp[N][N]; 9 void Change() 10 { 11 for(int i=1;i<=n;i++) 12 for(int j=0;j<n;j++) 13 if(tmp[i][j]=='*') mp[i]|=(1<<(n-j-1)); 14 } 15 int lowbit(int x) 16 { 17 return x&(-x); 18 } 19 void dfs(int k,int left,int right,int now) 20 { 21 if(k>n) 22 { 23 ans++; 24 return; 25 } 26 int t = mp[k]&(~left)&(~right)&(~now); 27 while(t) 28 { 29 int x = lowbit(t); 30 t-=x; 31 dfs(k+1,(left|x)<<1,(right|x)>>1,now|x); 32 } 33 } 34 int main() 35 { 36 scanf("%d",&n); 37 for(int i=1;i<=n;i++) scanf("%s",tmp[i]); 38 Change(); 39 dfs(1,0,0,0); 40 printf("%d\n",ans); 41 return 0; 42 }