洛谷P1562 還是N皇后
阿新 • • 發佈:2018-11-25
題目描述
正如題目所說,這題是著名的N皇后問題。
輸入輸出格式
輸入格式:
第一行有一個N。接下來有N行N列描述一個棋盤,“*”表示可放“.”表示不可放。
輸出格式:
輸出方案總數
輸入輸出樣例
輸入樣例#1:
4 **.* **** **** ****
輸出樣例#1:
1
這一道題和n皇后問題非常像,不同的是這一道題有些位置無法放置皇后,如果用搜索的話會超時,不過限制皇后的位置卻為狀態壓縮(位運算)提供了契機
限制皇后的位置無非就是這3種情況:
1.地形限制(輸入的限制)
2.行的限制(皇后會吃掉同行的皇后),這個其實可以忽略不計
3.列的限制(皇后會吃掉同列的皇后)
4.斜的限制(皇后會吃掉左斜和右斜的皇后)
程式碼:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cstdlib> #include<queue> #include<stack> #include<map> #include<cmath> #include<string> #include<set> #include<ctime> #define lowbit(x) x&-x using namespace std; inline int read(){ int x=0,f=0;char s=getchar(); while(!isdigit(s))f|=s=='-',s=getchar(); while( isdigit(s))x=(x<<1)+(x<<3)+s-48,s=getchar(); return !f?x:-x; } inline void print(int x){ if(x/10>0)print(x/10); putchar(x%10+'0'); } const int N=21; int n,sta[N];//sta表示每一行的限制 int flag,ans;//flag表示n個1,ans記錄結果 char st[N];//st輸入的時候用 void dfs(int now,int zuo,int you,int k){ if(now==flag){ans++;return;}//如果放完了 int p,pos=flag&(~(now|zuo|you|sta[k]));//pos表示限制 while(pos){ p=lowbit(pos);//樹狀陣列中的lowbit()可以求出第一個出現的1 pos^=p;//把1刪掉 dfs(now|p,(zuo+p)<<1,(you+p)>>1,k+1);//左斜到下一行就會左移一位,右斜右移一位 //我也不知道為什麼把(zuo+p)<<1改成(zuo|p)<<1會變慢 } } int main(){ //freopen("data.in","r",stdin); //freopen("std.out","w",stdout); n=read();flag=(1<<n)-1; for(int i=1;i<=n;i++){ scanf("%s",st+1);getchar(); for(int j=1;j<=n;j++) if(st[j]=='.')sta[i]|=(1<<(n-j)); } dfs(0,0,0,1); //now表示列的情況,zuo、you分別記錄被斜邊ban掉的行的情況,k表示第幾行 print(ans); return 0; }