1. 程式人生 > >N皇後問題(暴力dfs)

N皇後問題(暴力dfs)

std return 深度 比較 name 兩個 pac 遞歸 但我

題目:
N皇後在一個N*N的棋盤上,使其不能相互攻擊,即任意兩個皇後不得處於同一行,同一列或一條對角線上。

(皇後的攻擊是米字型,即不能同行不能同列,不能同對角線)

思路:

我們先假設n為一個小一點的數字,讓問題看起來簡單些,這裏假設n==4;

一行不可能放入兩個皇後, 而所有的皇後都要放進去, 所以每個皇後都在不同的行,每行必有一個皇後

我們從第一行開始,每取出一個皇後,放入一行,共有4種不同的放法;

然後再放第二個皇後,還是有4種不同的放法

此時就是一個四叉樹的結構

於是我們可以用一個四叉樹來描述這個過程。從根節點開始,樹每增加一層,便是多放一個皇後,

直到第四層(根節點為0層),最後得到一個完全四叉樹。  

緊接著我們開始用深度優先遍歷這個四叉樹,在遍歷的過程中,進行相應的條件的判斷。以便去掉不合規則的子樹。

  那麽具體用什麽條件來進行剪枝呢?

  我們先對問題解的結構做一個約定。

 用a[i]來表示 ,a[i]為第i行皇後所在的列數 (a實際為一種映射關系)

這時我們考慮第一個條件,不能在同一行,同一列於是我們得到a[i]不能相同。

剩下一個條件是不能位於對角線上,這個條件不是很明顯,但我們知道對角線的45°即斜率為1;

那麽設兩個不同的皇後分別在i,j行上,a[i],a[j]分別表示在i,j行哪一列上。

那麽在同一對角線的條件可以寫為abs((j-i))==abs(a[i]-a[j]),其中abs為求絕對值的函數(c++在<cmath>的頭文件裏>

#include <iostream>
#include <cmath>
using namespace std;
#define N 8
int sum=0;
int a[N+1]; //a為層數到列數的映射關系
void  dfs(int ceng)
{
    if(ceng==N+1)
    {
        for(int i=1;i<ceng;i++)  //這裏的比較很巧妙,比如層數是4,這裏就是1,2和1比,3和2和1比,4和3和2和1比;這樣就保證了任意兩層都比較過了
            for(int j=1;j<i;j++)
                
if(a[j]==a[i]||abs(i-j)==abs(a[i]-a[j])) return; sum++; return; //註意這裏兩種情況都要return; 不然會卡死在這個遞歸裏 } for(int i=1;i<=N;i++) { a[ceng]=i; dfs(ceng+1); } return; } int main() { dfs(1); //從第一層開始放 cout<<sum; return 0; }

0-0然後就可以了

這個方法是純暴力,把所有的可能情況都試了一遍,所以極其慢,要過hdu的話需要打表騙分

後來想了下,這道題用全排列可能寫起來更容易些,

嘛,電腦快沒電了,宿舍還沒來電,

等來電了再補上吧,

溜了溜了

N皇後問題(暴力dfs)