八皇后 :
这个代码只是输出一共有多少种摆放的个数。如果想要输出他摆放的不同方法
只需要在递归出口的时候用两个for循环输出棋盘即可。
目的在于每行,每列,以及对角线上都只能放置一个皇后,所以这里需要用到标记
目的在于我放置之后不能够再其对角线上这一行这一列再放。
首先定义一个10*10的二维数组,
8*8的也行,作为棋盘(全局变量的话不用传参,方便并且节省空间。
#include<stdio.h>
int a[10][10];
int sum=0;
int judge(int r,int c)
{
for(int i=0;i<8;i++)
{
if(a[i][c])
return 0;
}
for(int i=r,j=c;i>=0&&j>=0;i--,j--)
{
if(a[i][j])
return 0;
}
for(int i=r,j=c;i>=0&&j<8;i--,j++)
{
if(a[i][j])
return 0;
}
return 1;
}
void queen(int r)
{
if(r==8)
{
sum++;
return;
}
for(int i=0;i<8;i++)
{
if(judge(r,i))
{
a[r][i]=1;
queen(r+1);
a[r][i]=0;
}
}
}
int main()
{
queen(0);
printf("%d\n",sum);
return 0;
}
代码主要是由一个递归回溯的queen函数和一个判断是否能放置的judge函数以及main函数构成的。
我们的思路是让每一行放置一个皇后,然后去判断他能够放在这一行的那一列。每放置一个皇后就要对他所在的行列对角线做上标记。
当8行放完之后。sum++;函数调用结束。
不明白的同学可以看过来:
代码分析:
我们从第0行开始放皇后,当这8行都放完了,这就是一种方法。sum++(二维数组里的第一个坐标是行,第二个坐标是列)。
每次放都进入一个for循环里面去判断一下可以放在那一列,如果能放,就将这个位置标记为1,然后放下一行的皇后,一直到都放完之后
遇到return 结束,然后将a[r][i]你所坐的标记的清除,进入前面未结束的循环里面,继续找可以放置的位置。
这就是回溯。
一直到把所有能放置的方法都找到后结束函数。
judge()判断函数:
我们传参传过来了你所要放置皇后的下标,即位置,首先一个for循环判断它所在的这一个是否有被标记过,如果有就返回0,
它所在的行就不用判断了,因为我们就是一行一行的放置的。每行只放置一个所以就不用判断了;
对角线分为正对角线和反对角线
要注意是否越界的问题,所以是i>=0&&j>=0,在反对角线上是i>=0&&j<8
只需要判断你所放皇后以上部分就行了,因为下面的都还没有放,是一定符合判断的。