N皇后问题 状态压缩

。。。

用三个数组来保存他的每一个状态及(三个方向 ↖ ↑ ↗)

利用行减列 得到以下数字  所以在同一个主对角线上的 row-i是相同的 只需要标记vis[row-i+n]就知道在这主对角线时候已经有皇后了//+n是为了防止负数

    0  1  2  3   4

   -1  0  1  2  3

   -2 -1  0  1  2

   -3 -2 -1  0  1

    -4 -3 -2 -1  0 

#include <stdio.h>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int vis[3][50], P[15];//三个方向 ↖↑↗在此三个方向都不能有皇后
int n, sum;

void  DFS(int row);

int main()
{
    for(n = 1; n <= 10; n++)//先打表不然会超时的
    {
        memset(vis,0,sizeof(vis));
        sum = 0;
        DFS(1);
        P[n] = sum;
    }
    while(scanf("%d",&n), n)
    {
        printf("%d\n",P[n]);
    }
    return 0;
}

void  DFS(int row)
{
    int i;
    if(row == n + 1)//已经够n行了
    {
        sum ++;
        return ;
    }
    for(i = 1; i <= n; i++)
    {
        if(vis[0][row-i+n] == 0 && vis[1][i] == 0 && vis[2][i-row+n] == 0)
        {//不会回溯的同学要好好看看学习学习
            vis[0][row-i+n] = vis[1][i] = vis[2][i-row+n] = 1;//变值
            DFS(row + 1);//深搜
            vis[0][row-i+n] = vis[1][i] = vis[2][i-row+n] = 0;//回溯
        }
    }
}

选自 https://blog.csdn.net/xadillax/article/details/6512318

首先uplimit是(1 << n) - 1,如果n是8的话uplimit就是255,看做二进制就是11111111。聪明的人一看就知道了,这里每一位就代表一个皇后。

而r代表每一列能放与否,如10001110就代表第2、3、4、8个能放。

所以开始一个if来判断皇后放齐了没。如果齐了,显然r也要等于11111111。

还有ld和rd分别是对角线的各位能放与否。

我们来看看下图(From Matrix67):


假设我们已经递归到第三行了(左图),这里可以看出r为101010也就是说(第三行的)第二、四、六个格子可以放。ld是100100(蓝色线),(第三行的)第二、三、五、六个格子可以放,rd为000111,。 //当初看得我一脸懵

之后r|rl|rd 或运算 则有0的位就可以放A

col|lowbit//下一行的r,((lowbit|rl)>>1)下一行的rl (((lowbit|rd)<<1) 下一行的rd  &high//保证在数据范围内 可以截掉 why?

col|lowbit 其实就是将r中的刚刚放A的位置 0变为1

lowbit|rl 也是  将rl中的刚刚放A的位置 0变为1 但还要移位>>1 why?


#include<stdio.h>
int n,high,ans;
void dfs(int col,int fir,int sec)
{
    if(col==high){ans++;return;}
    int canput=((~(col|fir|sec))&high);
    while(canput)
    {
        int lowbit=(canput)&(-canput);
        dfs((col|lowbit),((lowbit|fir)>>1),(((lowbit|sec)<<1)&high));
        canput&=(~lowbit);
    }
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        ans=0;
        high=(1<<n)-1;
        dfs(0,0,0);
        printf("%d\n",ans);
    }
    return 0;
}

posted @ 2018-03-31 16:50  LandingGuys  阅读(267)  评论(0编辑  收藏  举报