【八皇后問題和算法介紹】
簡書上看到一篇極好的文章:點這跳轉
算法簡單易懂,只寫八皇后太沒意思,乾脆讓用戶指定皇后數量,寫個升級版的“N皇后”問題。
【運行情況概覽】
輸入一個正數n(不超過20),輸出對應n皇后問題的解:
1
(1)
1皇后問題有1組解,以上呈現各行皇后分別放在第幾列
2
2皇后問題無解
3
3皇后問題無解
4
(2 4 1 3)
(3 1 4 2)
4皇后問題有2組解,以上呈現各行皇后分別放在第幾列
5
(1 3 5 2 4)
(1 4 2 5 3)
(2 4 1 3 5)
(2 5 3 1 4)
(3 1 4 2 5)
(3 5 2 4 1)
(4 1 3 5 2)
(4 2 5 3 1)
(5 2 4 1 3)
(5 3 1 4 2)
5皇后問題有10組解,以上呈現各行皇后分別放在第幾列
6
(2 4 6 1 3 5)
(3 6 2 5 1 4)
(4 1 5 2 6 3)
(5 3 1 6 4 2)
6皇后問題有4組解,以上呈現各行皇后分別放在第幾列
【示例代碼】
#include<stdio.h>
//#define MAXSIZE 20;
//int a[MAXSIZE][MAXSIZE]; //這種定義方式在Xcode中會報蜜汁錯誤:Unexpected ';' before ']'
int a[20][20];
int n;
int total;
int FindIndexOfOne(int row){ //找到第row行皇后的列數(從0開始計數)
for(int col=0;col<n;col++){
if(a[row][col]==1)return col;
}
return -1;
}
void PrintAns(){ //打印各行皇后的列數(從1開始計數)
int row;
printf("(");
for(row=0;row<n-1;row++){
printf("%d ",FindIndexOfOne(row)+1);
}
printf("%d)\n",FindIndexOfOne(row)+1);
}
int NoAttack(int row,int col){ //檢測row行col列位置放置的皇后是否不會被攻擊
for(int i=0-n;i<n;i++){
if(row+i>=0&&row+i<n&&col+i>=0&&col+i<n&&a[row+i][col+i]==1)return 0;
if(row+i>=0&&row+i<n&&a[row+i][col]==1)return 0;
if(row+i>=0&&row+i<n&&col-i>=0&&col-i<n&&a[row+i][col-i]==1)return 0;
if(col-i>=0&&col-i<n&&a[row][col-i]==1)return 0;
}
return 1;
}
void FindQueen(int row){ //算法核心
if(row>=n){ //遞歸邊界,此時已經求出一種解
PrintAns();
total++;
}
else{
for(int col=0;col<n;col++){
if(NoAttack(row,col)==1){
a[row][col]=1;
FindQueen(row+1);
a[row][col]=0; //比較難懂的一步,作用是回溯時清楚這個位置上的皇后,不然棋盤最終會被擺上超過n個皇后。
//因爲找齊n個皇后就直接輸出結果,所以清除也不會影響結果
}
}
}
}
int main(){
total=0;
while(scanf("%d",&n)==1){
FindQueen(0); // 誤將0寫成n,FindQueen的參數是一個整數,意思是從第幾行開始找皇后
if(total!=0){
printf("%d皇后問題有%d組解,以上呈現各行皇后分別放在第幾列\n",n,total);
}
else printf("%d皇后問題無解\n",n);
total=0;
}
return 0;
}