八皇后问题(典型的递归回溯)

来源:互联网 发布:有人招聘网络写手吗? 编辑:程序博客网 时间:2024/04/30 06:42

八皇后 :
这个代码只是输出一共有多少种摆放的个数。如果想要输出他摆放的不同方法
只需要在递归出口的时候用两个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
只需要判断你所放皇后以上部分就行了,因为下面的都还没有放,是一定符合判断的。

1 0
原创粉丝点击