题解 P1219 【八皇后】

· · 题解

这道题其实我还没学回溯就写了,大概思路就是:

搜索,二进制优化。

先附上代码

#include<bits/stdc++.h>
using namespace std;//用位运算优化
int n,mans,p;
int mark[100],bin[1<<20];
void dfs(int x/*行*/,int a,int b,int c){//列,左上角,右上角标记 
    if(x>n){
        ans++;
        if(ans>=1&&ans<=3){
            for(int i=1;i<=n;i++)printf("%d ",mark[i]+1);//输出标记了的列 
            puts("");
        }
        return;
    }
    int t=(a|b|c)^p;//p记录棋盘下标范围,t判断是否在棋盘内
    while(t) {
        int i=t&(-t);//二进制找到最后一个的全值 
        mark[x]=bin[i];//选择当前棋子 
        dfs(x+1,a|i,(b|i)>>1,((c|i)<<1)&p);//对当前棋子做标记,继续查找 
//a|i记录当前列不能走,b|i表示左上角,(c|i)<<1)&p查找右上角与当前列的重合 
        t-=i;
    }
}
int main(){
    scanf("%d",&n);
    p=(1<<n)-1;//用二进制表示下标范围;
    bin[0]=1;
    for(int i=1; i<=n; i++)bin[1<<i]=i;//二进制标记归位 
    dfs(1,0,0,0);
    printf("%d",ans);
    return 0;
}

不难看出,代码中用了二进制表示坐标,因为位运算比一般的运算要快很多,所以过程也是比较快的!

第一次写题解,希望采纳,谢谢!