N皇后问题,做之前感觉挺难,但做着做着发现其实还挺简单的。用递归写的代码简直不要太简洁!
令N=8,效果如图:
在这里我列出了四种解法,具体讲解见注释:
C语言解法
C++解法
C语言解法升级版
C++解法升级版
其中普通版利用的是二维数组,升级版用的是一维数组。
用二维数组来做直观,好理解,但效率比用一维数组低。
感觉 面向对象的C++ 的确和 面向过程的C 在思想上有较大区别,以前真的是拿C++当C用,,,
话不多说,开始解题。
二维数组解法
C语言
(用到了我之前从来没用过的全局变量)
(不过老师上课好像讲过不建议定义全局变量。。)
#include<stdio.h>
#define maxsize 20
#define occupied 1
#define not_occupied 0
/** 全局变量定义棋盘,
* 这样调用函数时就不用把这个二维数组传来传去了。**/
bool queen_square[maxsize][maxsize]={
not_occupied};
int size;
int answer_num=1;
/**三个函数分别用来:
* 检查当前位置可不可以放
* 打印棋盘
* 递归求解 **/
bool unguarded(int row, int col);
void print();
void solve(int row);
unguarded函数:判断当前位置是否可以放
(因为我写的这个递归是从最下面的一行开始放皇后,所以要检查的是当前行的“下面的”棋盘)
bool unguarded(int row, int col)
{
bool ok=true;
int i=0;
for(i=0 ; i<size && ok ;i++)//检查该列
{
if(queen_square[i][col]==occupied)
ok=false;
}
for(i=1 ; row+i<size&&col+i<size&&ok ; i++)//检查指向左下的对角线
{
if(queen_square[row+i][col+i]==occupied)
ok=false;
}
for(i=1 ; row+i<size&&col-i>=0&&ok ; i++)//检查指向右下的对角线
{
if(queen_square[row+i][col-i]==occupied)
ok=false;
}
return ok;
}
print函数:打印棋盘,无需赘述。
void print()
{
printf("THE %d ANSWER:\n\n",answer_num++);
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
if(queen_square[i][j]==occupied)
printf(" O ");
else printf(" + ");
}
printf("\n\n");
}
printf("\n\n");
}
solve函数:递归函数,在第row行放皇后。
void solve(int row)
{
if(row<0)//row=-1,说明第零行已经放上了皇后,所以此时要把棋盘打印出来
print();
else
{
for