N皇后問題(搜索)

N皇后問題

Problem Description

在N*N的方格棋盤放置了N個皇后,使得它們不相互攻擊(即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。
你的任務是,對於給定的N,求出有多少種合法的放置方法。

Input

共有若干行,每行一個正整數N≤10,表示棋盤和皇后的數量;如果N=0,表示結束。

Output

共有若干行,每行一個正整數,表示對應輸入行的皇后的不同放置數量。

Sample Input

1
8
5
0

Sample Output

1
92
10

解題思路

這道題主要考察的是回溯的思想。
我們以5個皇后爲例講這道題
首先我們把第一個皇后放在(1,1)處。那麼很顯然,第一行第一列以及(i,i)點所處位置即45度斜線方向都不可以放皇后了


我們看下一個皇后應該放在那裏。(先看列再看行),很顯然第一列不可以放了,第二列第一行即(1,2)不可以。第二列第二行(2,2)可以。那麼我們放第二個皇后,同時按要求把他鎖在的行列和45度角方向畫上斜線

同上面的步驟一樣,我們再找下一個皇后位置(2,3)。

我們可以看出來,這樣放過(2,3)之後就在也放不下下一個皇后了。所以這種方法一共只能放三個皇后。是不合法的。
此時我們就用到了回溯。就是恢復到上一個放的皇后(2,2)哪裏。重新找下一個皇后,而且我們知道在找到(2,3)皇后之前我們已經判斷過哪些點了,所以我們緊接着判斷(2,3)後面的點(2,4)就可以了,並且我們一定要把(2,3)位置恢復成沒有標記過的點。

找到下一個皇后(第三個皇后)位置爲(5,3).

找第四個皇后位置(2,4)

找到第五個皇后位置

我們可以看出5個皇后已經都安排好位置了。我們再重新從空表開始,確定第一個皇后的位置就是(2,1)。按以上步驟找就可以了

代碼
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;

int n;
int erwei[12][12];       //標記是否可以放皇后
int hang[12];             //標記行是否可以放皇后
int lie[12];					//標記列是否可以放皇后
int sum;					//一共有幾種方法
int table[12];            //幾個皇后對應的有幾種方法

bool check(int i, int j)
{
    int  s,t;
    if(hang[i]) return false;  //這一行已有皇后,該位置不合法。 
    if(lie[j]) return false;      //這一列已有皇后,該位置不合法。 
    for(s=i-1,t=j-1;s>=0&&t>=0;s--,t--) //判斷左上角有沒有皇后。
    {
        if(erwei[s][t]) return false;
    }
    for(s=i+1,t=j+1;s<n&&t<n;s++,t++) //判斷右下角有沒有皇后。
    {
        if(erwei[s][t]) return false;
    }
    for(s=i-1,t=j+1;s>=0&&t<n;s--,t++) //判斷右上角有沒有皇后。
    {
        if(erwei[s][t]) return false;
    }
    for(s=i+1,t=j-1;s<n&&t>=0;s++,t--) //判斷左下角有沒有皇后。
    {
        if(erwei[s][t]) return false;
    }
    return true;
}
void dfs(int j)
{
    if(j==n)
    {
        sum++;
        return;
    }
    for(int i=0;i<n;i++)
    {
        bool flag=check(i,j);  //判斷該位置是否可以放皇后
        if(flag)         //如果該位置可以放
        {
            erwei[i][j]=1;
            hang[i]=1;
            lie[j]=1;
            dfs(j+1);  //判斷下一列
            erwei[i][j]=0;
            hang[i]=0;
            lie[j]=0;
        }
    }
}
int main()
{
    for(int i=1;i<=10;i++)
    {
        memset(erwei,0,sizeof(erwei));
        memset(hang,0,sizeof(hang));
        memset(lie,0,sizeof(lie));
        n=i;
        sum=0;
        dfs(0);
        table[i]=sum;
    }
    while(scanf("%d",&n))
    {
        if(n==0)
            break;
        printf("%d\n",table[n]);
    }
    return 0;
}

親們 寫博客不易 留個贊吧。不懂的歡迎提問哦!!!

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