n皇后问题(位运算优化)

n皇后问题

题目描述:
众所不知, rly现在不会玩国际象棋。但是,作为一个OIer, rly当然做过八
皇后问题。这里再啰嗦几句,皇后可以攻击到同行同列同对角线,在n*n的方格中摆n个皇后使其互不攻击到,求不同的解的数量,这就是经典的n皇后问题。
现在问题推广到n皇后问题,这个问题对于你而言实在是小菜一叠。但因为上一次rly把棋盘弄破了,又拿不出新的,所以rly打算难一点点,问题就是破棋盘上的n皇后问题。他想知道……(你们懂的)。
棋子都是相同的。
输入说明:
一行,一个正整数N。
接下来N行,每行N个数,要么为0,表示没坏,要么1,表示坏了。
输出说明:
一行,输出不同的解的数量。
样例输入:
4
1 0 1 1
1 1 1 0
0 1 1 1
1 1 0 1
样例输出:
1
数据范围:
对于40%的数据, N<=13。
对于100%的数据, N<=16。
其中有30%的数据,棋盘没有破(你可以认为rly又去买了一个新的)。

#include
#include
using namespace std;
const int maxn=30;
int n,ans,a[maxn];
void dfs(int t,int l,int x,int y)//当前行t的状态,x用二进制表示一条对角线,y用二进制表示另一条对角线的状态 
{
    if(t==n+1)
    {
        ans++;
        return;
    }
    int s=((1<1)&(~(a[t]|l|x|y));
    /*
    S存的能放的位置 先把行 列 对角线或起来现在1表示已经放过 
    然后取反后1代表没放过能放得到能放的 
    */
    while(s)
    {
        int z=s&(-s);//lowbit找能放的位置-->即找1 
        dfs(t+1,l+z,(z+x)<<1,(y+z)>>1);//l,x,y能更新放的位置(对角线到下一行会移一列)
        s-=z;
    }
}
int main()
{
    freopen("queen.in","r",stdin);
    freopen("queen.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int x;
            scanf("%d",&x);
            if(x) a[i]+=(1<1);
        }
    }
    dfs(1,0,0,0);
    cout<return 0;
}

你可能感兴趣的:(题目,搜索)