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 }

 

posted @ 2021-02-13 00:10  acmloser  阅读(92)  评论(0编辑  收藏  举报