N-皇后的回溯解法
阿新 • • 發佈:2019-02-15
回溯演算法的基本思想是:從一條路往前走,能進則進,不能進則退回來,換一條路再試。
a[N_size]用來儲存每一行皇后所在列數,a[4]=4代表第四行的皇后放在第4列.#include <stdio.h> #include <math.h> #include <stdlib.h> #define N_size 7 #define INITIAl -1000 int N=N_size; int count = 0; void init(int a[]) { int *p = a; for(int i = 0; i<=N_size; i++) { *p = INITIAl; p++; } } void Print(int a[]) { for(int i = 0; i<=N-1; i++) { //printf("第%d行, a[i] is:%d\n",i, a[i]); for(int j = 0; j<=N-1; j++) { if(a[i] == j) printf(" #"); else printf(" ."); } printf("\n"); } } bool can_place(int i, int j, int a[]) //判斷第i行, 第j列是否可以放置皇后 { for(int m = 0; m<=N-1; m++) { //printf("第 %d 行, 第%d 列, a[m] is: %d.\n", i, j, a[m]); if((a[m] == j) || (abs(a[m] - j) == abs(m-i))) return false; } return true; } void queens(int N, int i, int a[]) { //往第i行放置皇后:前i-1行已經放好 if(i == N) //it's time to print the result { Print(a); count++; } else { for(int j = 0; j<=N-1; j++) { if(a[i] == INITIAl) //若a[i]的值為initial, 則說明第i行還沒有放置皇后 { if(can_place(i, j, a)) { printf("可以往第%d行 第%d列 放置皇后\n",i, j); a[i] = j; //place at (i,j):第i行, 第j列 queens(N, i+1, a);//繼續往第i+1行放置皇后 //如果在第i行第j列放置皇后之後, 能繼續探索到第i+1行的皇后放置位置, 並最終找到在第N-1行放置皇后的位置, 則會輸出最終結果 //否則, 假設在第i+1行就找不到合適的位置,則queens(N, i+1, a)函式會什麼也不輸出, 並返回到這裡的a[i] = INITIAl //意味著取消之前的第i行位置, 從下一個j進行判斷, 判斷第i行第j+1列是否可以放置 a[i] = INITIAl;//這一句實現回溯到上一層 } } } } } int main() { int a[N_size]; //需要在防止皇后前對a進行初始化, 且每個元素值都是負數, 否則會自動初始化為全0, a[0] = 0,即預設將第0行的皇后放在了第一列 init(a); queens(N_size, 0, a); printf("共有%d種解法.", count); }