八皇后問題的n種解法


 經典的八皇后問題:在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。

很早就接觸過八皇后問題,最近數據結構作業中又看到了這個題目,仔細研究了一波網上諸位大牛的博客,發現這個問題居然有這么多有趣的優化。

1.經典的回溯遞歸解法:

#include<stdio.h>
#include<iostream>
using namespace std;
//dfs,每行只能放一個元素,遍歷每行的每個位置,用一個一維數組記錄,最后檢查是否符合要求
int ans; int vis[10]; int abs(int x){ return x > 0 ? x : -x; } bool check(int r,int c){ for(int i = 1;i<r;i++){ if(vis[i] == c) return false; if(vis[i] - c == r - i || vis[i] - c == i - r) return false; } return true; } void dfs(int r){ if(r > 8){ ans++; return; } for(int i = 1;i<=8;i++){ if(check(r,i)){ vis[r] = i; dfs(r+1); vis[r] = 0; } } } main(){ dfs(1); cout<<ans<<endl; }

2.對角線檢查優化

/*用三個數組記錄列,左對角線,右對角線信息,每次判斷該位置是否符合要求,只在符合要求位置放置元素。*/
#include <iostream>
using namespace std;
const int maxn=105;
const int mo=100;
typedef long long ll;
int a[maxn],n = 8,ans=0;
bool b[maxn],c[maxn],d[maxn];
void sou(int x){
    if(x > n){
        ans++;
        return;
    }
    for(int i = 1;i <= n;i++)if(!(b[i] || c[x+i] || d[x-i+n])){
        b[i] =c [x+i]=d[x-i+n]=true;
        a[x] = i;
        sou(x+1);
        b[i] =c [x+i] = d[x-i+n]=false;
    }
}
int main(){
    sou(1);
    cout<<ans;
}

3.位運算:

//算法思想與上一相同,改用三個int來存儲信息,采用位運算提取合適位置
#include<iostream>
#include<stdio.h>
using namespace std;
int board;
int n;
int ans = 0;
void n_queen(int col,int ld,int rd){
    if(col == board){
        ans++;
        return;
    }
    int pos = board & (~(col | ld | rd));
    while(pos){
        int p = pos & (-pos);
        pos = pos - p;
        n_queen(col | p , (ld | p) << 1,(rd | p) >> 1);
    }
}
int main(){
    cin>>n;
    board = (1 << n) - 1;
    n_queen(0,0,0);
    cout<<ans<<endl;
}

4.十行內的八皇后...

https://www.zhihu.com/question/28543312

對知乎上各路大大的炫技佩服的五體投地,更改了一下上一代碼,勉強也達到了十行的要求。。。

#include<iostream>
int n_queen(int col,int ld,int rd,int board){
    if(col == board) return 1;
    int tot = 0;
    for(int pos = board & (~(col | ld | rd)); pos != 0;pos -= (pos & (-pos))) tot+=n_queen(col | (pos & (-pos)) , (ld | (pos & (-pos))) << 1,(rd | (pos & (-pos))) >> 1,board);
    return tot;
}
int main(){
    std::cout<<n_queen(0,0,0,(1<<8)-1);
}

小結:斷斷續續研究了兩天各類八皇后寫法,感覺自己對位運算的運用加深了一個層次,更大的收獲還是知道了自己的渺小,一個原以為十分簡單的八皇后都可以衍生出這么多東西,遞歸的非遞歸的,全排列搜索的,回溯法的,甚至還有廣搜版本的八皇后...,學習之路果然永無止境


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM