算法經典搜索問題--八皇后

在介紹八皇后問題之前我們先說說dfs吧

DFS–深度優先搜索

咱們先來看看我的dfs入坑題:指數型枚舉

#include<iostream>

using namespace std;

int n;

void dfs(int k,int choose)
{
    if(k==n)
    {
        for(int i=0;i<n;i++)
        {
            if(choose>>i&1) cout<<i+1<<" ";
        }
        puts("");
        return;
    }
    dfs(k+1,choose);//不選
    dfs(k+1,choose|(1<<k));//選
}
int main(){
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
    cin>>n;
    dfs(0,0);


    return 0;
}
//輸入:3
//輸出:

//3 
//2 
//2 3 
//1 
//1 3 
//1 2 
//1 2 3 

這道題比較經典,可以看出dfs讓我們能暴力枚舉了所有的決策(選或者不選),如果你能理解這題那麼恭喜你,你dfs入門了。在數據量較小時暴力dfs無疑時非常優秀的選擇。好下面我們直接給出八皇后問題的代碼。

#include<iostream>

using namespace std;

int queen[8][8];//當然也可以用二進制表示但可能比較複雜,咱們就不自己難爲自己了
int res=0;
void copy(int a[8][8],int b[8][8])
{
    for(int i=0;i<8;i++)
        for(int j=0;j<8;j++)
            a[i][j]=b[i][j];

}

void work(int a,int b)//選中a行b列
{
    for(int i=0;i<8;i++)
        queen[a][i]=1;
    for(int i=0;i<8;i++)
        queen[i][b]=1;
    //對角線比較騷,咱們寫的細心一點就不會錯了
    //先寫主對角線
    int d=a-b;
    int i=a-b,j=0;
    while(i<8&&j<8)
    {
        if(i>=0&&j>=0)
            queen[i][j]=1;
        i++;
        j++;
    }
    //最後
    d=a+b;
    i=a+b,j=0;
    while(i>=0&&j<8)
    {
        if(i<8&&j>=0)
            queen[i][j]=1;
        i--;
        j++;
    }
}
void dfs(int k)
{
    if(k==8)
    {
        res++;
        return;
    }
    int i=k;
    int g[8][8];//工具人放函數裏面不容易錯還舒服一點
    copy(g,queen);
    for(int j=0;j<8;j++)
    {
        if(!queen[i][j])
        {
            work(i,j);
            dfs(i+1);
            copy(queen,g);//還原現場
        }
    }
}
int main(){
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
    dfs(0);
    cout<<res<<endl;
    return 0;
}

八皇后問題時道非常經典的dfs問題,與上題類似我們枚舉所有決策就可以了,與之不同的是我們很容易分析出每行(列)有且只有一個皇后,與之不符就一定不行,在此基礎上dfs能太高不少的效率。其實這個方法也可以叫剪枝,但不是我們今天討論的重點。
我們模擬決策之後,就可以寫代碼了,別忘了工具人數組一定要放在函數裏面,還有就是對角線一定要注意,注意好這幾點,想必大家很容易就能把此題解出來了。=。=

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章