N皇后問題 回溯法
阿新 • • 發佈:2019-01-22
回溯法過程
在試探過程中,皇后的放置需要檢查她的位置是否和已經放置好的皇后發生衝突,因此需要一個檢查函式
假如兩個皇后被放置在(i,j)和(k,l)上 ,當且僅當 |i-k|==|j-l| 時兩個皇后在同一條對角線上。
(1).先從首位開始檢查,如果不能放置,則檢查該行的第二個位置,依次進行下去,直到找到一個可以放置皇后的位置,儲存當前狀態,然後轉下一行重複該操作。
(2).如果檢查該行所有位置均不能放置,說明上一行放置的皇后無法讓所有的皇后找到自己合適的位置。因此就要回溯到上一行,繼續檢查該皇后後面的位置。
附程式碼
#include <iostream> #include <cmath> #include <cstdio> using namespace std; int ans = 0,queen[15]; int n,num[15]; int check(int x) //用於檢查皇后是否可以放在此位置 { for(int i = 0;i<x;i++) { //queen[i] == queen[x] 用於保證元素不在同一列 //abs(queen[i] == queen[x] == abs(n-i)) 用於約束元素不在同一行且不在同一條斜線上 if(queen[i] == queen[x] || abs(queen[i] - queen[x]) == abs(x-i)) return 0; } return 1; } //核心函式 回溯法思想 void NQUEEN(int x) //回溯嘗試皇后的位置 { for(int i = 0;i<n;i++) { //首先將皇后放置在第0列的位置 queen[x] = i; //姜皇后擺在當前迴圈到的位置 if(check(x)) { if(x == n-1) ans++; // 如果全都擺好,則ans++ else NQUEEN(x+1); // 否則繼續擺下一個皇后 } } } void init() //一定要打表,不然會超時 { for(n = 1;n<=10;n++) { ans = 0; NQUEEN(0); //從橫座標0開始嘗試 num[n] = ans; } } int main() { init(); while(scanf("%d",&n)) { if(n == 0) break; printf("%d\n",num[n]); } }