n皇后問題—回溯法


一、問題簡介

描述

在n×n 格的棋盤上放置彼此不受攻擊的n 個皇后。按照國際象棋的規則,皇后可以攻擊與之處在同一行或同一列或同一斜線上的棋子。n后問題等價於在n×n格的棋盤上放置n個皇后,任何2 個皇后不放在同一行或同一列或同一斜線上。 設計一個解n 后問題的隊列式分支限界法,計算在n× n個方格上放置彼此不受攻擊的n個皇后的一個放置方案。

Input

輸入數據只占一行,有1 個正整數n,n≤20。

Output

將計算出的彼此不受攻擊的n個皇后的一個放置方案輸出。第1行是n個皇后的放置方案。

Sample Input

5

Sample Output

1 3 5 2 4

二、問題分析

回溯法解的生成

回溯法對任一解的生成,一般都采用逐步擴大解的方式。每前進一步,都試圖在當前部分解的基礎上擴大該部分解。它在問題的狀態空間樹中,從開始結點(根結點)出發,以深度優先搜索整個狀態空間。這個開始結點成為活結點,同時也成為當前的擴展結點。在當前擴展結點處,搜索向縱深方向移至一個新結點。這個新結點成為新的活結點,並成為當前擴展結點。如果在當前擴展結點處不能再向縱深方向移動,則當前擴展結點就成為死結點。此時,應往回移動(回溯)至最近的活結點處,並使這個活結點成為當前擴展結點。回溯法以這種工作方式遞歸地在狀態空間中搜索,直到找到所要求的解或解空間中已無活結點時為止。

回溯法與窮舉法

回溯法與窮舉法有某些聯系,它們都是基於試探的。窮舉法要將一個解的各個部分全部生成后,才檢查是否滿足條件,若不滿足,則直接放棄該完整解,然后再嘗試另一個可能的完整解,它並沒有沿着一個可能的完整解的各個部分逐步回退生成解的過程。而對於回溯法,一個解的各個部分是逐步生成的,當發現當前生成的某部分不滿足約束條件時,就放棄該步所做的工作,退到上一步進行新的嘗試,而不是放棄整個解重來。

解題思路

  1. d[i]=k 表示第 i 個皇后放在第 k 個位置上,
  2. 然后從第1個皇后,第1個位置開始,每次放置前先調用 check() 函數判斷與其他皇后是否沖突
  3. 如果不沖突則放置
  4. 如果沖突則移至下一個位置,如果位置到了最后一個,則不放,且將上一次放置的皇后移至下一個位置,遞歸調用。
  5. 直至放置完畢所有皇后(flag=true) 或者 所有位置遍歷結束。

三、代碼

#include <iostream>
#include <stdlib.h>
using namespace std;

int n=0;
int d[21];
bool flag = false;
void backtrack(int);
bool check(int);

int main(){
    cin>>n;

    backtrack(1);
    for(int i=1;i<n;i++)
        cout<<d[i]<<' ';
    cout<<d[n];
}
void backtrack(int k){

    if (k == n+1){
        flag=true;
        return;
    }
    for (int i=1;i<=n;i++){
        d[k] = i;
        if (check(k))
            backtrack(k+1);
        if (flag)
            return;
        d[k] = 0;
    }
}
bool check(int k){
    for (int i=1;i<=k;i++)
        for (int j=i+1;j<=k;j++)
            if (d[i] == d[j] || abs(d[i] - d[j]) == abs(i-j))
                return false;

    return true;
}

python版

n = int(input())
d = [0] * (n+1)
flag = 0


def check(k):
    if k == 1:
        return True
    for i in range(1, k+1):
        for j in range(i+1, k+1):
           # print(j,end=' ')
            if d[i] == d[j] or abs(d[i] - d[j]) == abs(i-j):
                return False

    return True



def dfs(k):

    global flag
    if k == n+1:
        flag=1
        return
   # print('k =', k)
    for i in range(1, n+1):
        d[k] = i
       # print('d[',k,'] = ',i,sep='')
        if check(k):
            dfs(k+1)

        if flag == 1:
            return
        d[k] = 0


dfs(1)
for x in d[1:n]:
    print(x,end=' ')
print(d[n],end='')


免責聲明!

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



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