【八皇后问题和算法介绍】
简书上看到一篇极好的文章:点这跳转
算法简单易懂,只写八皇后太没意思,干脆让用户指定皇后数量,写个升级版的“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;
}