N皇后問題

N皇后問題

回溯法(探索與回溯法)是一種選優搜索法,又稱爲試探法,按選優條件向前搜索,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術爲回溯法,而滿足回溯條件的某個狀態的點稱爲“回溯點”。

基本思想

在包含問題的所有解的解空間樹中,按照深度優先搜索的策略,從根結點出發深度探索解空間樹。當探索到某一結點時,要先判斷該結點是否包含問題的解,如果包含,就從該結點出發繼續探索下去,如果該結點不包含問題的解,則逐層向其祖先結點回溯。(其實回溯法就是對隱式圖的深度優先搜索算法)。 若用回溯法求問題的所有解時,要回溯到根,且根結點的所有可行的子樹都要已被搜索遍才結束。 而若使用回溯法求任一個解時,只要搜索到問題的一個解就可以結束

1.問題描述

n皇后問題是遞歸和回溯法的一個典型應用。問題描述如下:對於一個n×n的棋盤,要求在其中放入互不攻擊的n個皇后。
皇后的攻擊範圍包括:
1) 同一行
2) 同一列
3) 同一對角線(包括兩個方向)

2.算法設計

問題的解可表示爲x[1:n], 表示皇后i放在棋盤的第i行的第x[i]列。
a)x[i]≠x[j] ,i≠j:不允許將任何兩個皇后放在同一列上;
b)|j-i|≠|x[j]-x[i]|: 不允許兩個皇后位於同一條斜線上。

3.算法步驟

取K爲行的編號,數組X[K]爲列的編號,先令K=1,X[K]=1,然後取K=K+1,對棋盤的下一行進行檢測,找到合法的位置,依次檢測,直到K=N 時,輸出皇后的所在的列的位置;若過程中遇到在某一行K 無合法位置,則取K=K-1,回溯到上一行,同時令X[K]=X[K]+1,再對下一行的位置進行檢測,看是否有合法皇后位置,依次得到所有的結果。

程序代碼如下:

#include <stdio.h> 
#include <math.h> 
typedef int bool; 
#define true  1; 
#define false  0; 
//檢測皇后是否合法
bool place(int k, int *X) 
{ 
   int i;         
i=1; 
   while(i<k){ 
     if((X[i]==X[k])||(abs(X[i]-X[k])==abs(i-k)))
       return false;                                        i++;
        } 
      return true; 
}
 void  Nqueens(int n,int *X) { 
   int k;
   X[1]=1;     
k=1;//k表示棋盤的列,用X[k]表示當前列的行的編號
while(k>0){             
int i; 
    X[k]=X[k]+1; //不斷的在解空間裏從小到大的試探
while((X[k]<=n)&&(!place(k, X))) 
    X[k]=X[k]+1; //不符合條件的馬上再取解空間的下一個值來試探。
    if(X[k]<=n)   //找到了一個位置,而且是合法的 
     if(k==n) {  //是不是最後一個皇后,若是則得出一個完整解
     for( i=1;i<=n;i++)
            printf("%d",X[i]);
             printf("\n");
                   } 
      else  {//若不是最後一個皇后,則給下一個皇后找位置
      k=k+1;
      X[k]=0;
          }
   else     
k=k-1; //若是找了全部的列都無法放置某個皇后,則回溯到上一個k的情況 
        } 
} 

void main() { 
        int n; 
        int X[100]; 
        printf("請輸入皇后的個數:");
         scanf("%d",&n); 
        printf("問題的解有:"); 
      Nqueens(n,X); }
發佈了81 篇原創文章 · 獲贊 141 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章