P1562 还是N皇后(搜索 进制 位运算,按位)

P1562 还是N皇后:P1562 还是N皇后(搜索 进制 位运算,按位)_第1张图片

利用二进制的特殊性,将每一行的状态用一个二进制数表示
例如:n=4第一行的状态都可放,用0000表示第一行的状态 表示这一行每个位置都可以放皇后(1表示不可放,0表示可放),这样我们可以在先选择其中一个位置放上皇后,假如放在第一位,则这一行的状态变为1000,将其传到下一行(姑且认为是第二行),我们就知道第一个第位置不可方皇后了(根据每一列只可以放一个皇后),当然还有限制每个对角线上只能放置一个皇后,那怎么办呢?当然有办法,将上一行的1000状态分别进行左移和右移运算得到0000和0100,并传到第二行,将其与行状态(1000)进行或运算得到1100,那么我们就知道第一位置和第二个位置不可放皇后(第一个是因为上一行第一个位置放了皇后,而第二个位置不能放是因为不能与第一行的皇后在同一个对角线上)。这样我们就从第三四个位置选择.
不断循环这个方法,直到每一行都放置完,方法数加一。(大体就是这个意思)
下列是需要注意的几点:

  1. 二进制左移时一般不会溢出,但我们只需要二进制的后n位
  2. 我们知道逐位扫描法(找到一个数的二进制数形式的第一个1的位置(从低位向高位),这样我们将二进制状态去反,运用其可以选择出其中可以放置皇后的点、

代码如下:

#include
#include
using namespace std;
char s[17];
int p[17]={0};
int n;
int END;
int ans=0;
int lowbit(int t)
{
    return t&(-t);
}
void dfs(int hang,int left,int right,int h)//依次是  行状态,左对角线,右对角线,第h行
{
    if(END==hang)//全部放完////////////
    {
        ans++;//方法数加一
        return;
    }
    int y,m;
    int cur= hang | left | right | p[h];//第h行的状态
    m= (~cur) & END;//取反    并除去高位的影响
    while(m)
    {
        y=lowbit(m);
        m-=y;
        dfs(hang+y,(left+y)<<1,(y+right)>>1,h+1);
    }
}
int main()
{
    cin>>n;//输入n
    cin.ignore();
    for(int i=0;i

你可能感兴趣的:(练习题目)