1. 程式人生 > >n皇后問題(位運算優化)

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<iostream>
#include<cstdio>
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<<n)-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<<j-1); } } dfs(1,0,0,0); cout<<ans; fclose(stdin);fclose(stdout); return 0; }