利用回溯的八皇后问题

来源:互联网 发布:天人网络电视apk 编辑:程序博客网 时间:2024/05/17 20:48
       八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。

 

利用回溯法解决这个问题:

       回溯算法的基本思想是:从一条往前走,能进则进,不能进则退回来,换一条路再试。

       书面一点:从问题的某一种状态出发,搜索可以到达的所有状态;

                        当某个状态到达后(即满足了要求) 或者该状态不符合要求,可向前回退,并继续搜索其他可达到的状态;

                        当所有状态都到达后,回溯算法结束。

 

    算法解决思路:

       1.初始化: i = 1;  //行

       2.初始化: j = 1;  //列

       3. 从第i行开始,恢复j的当前值,判断第j个位置:

           a、 位置j可放入皇后:标记位置(i,j),i++, 执行步骤2

           b、 位置j不可放入皇后:j++,执行步骤a;

           c、 当j>8时,i--(回溯),执行步骤3。

       4. 结束: 当第8行可以放入皇后。

程序代码:

#include <stdio.h>#define N 8typedef struct Pos  //记录偏移量{int i;int j;}Pos;static char board[N+2][N+2];  //增加边界,方便递归使用static Pos pos[] = {{-1, -1}, {-1, 0}, {-1, 1}}; //正对角线上,每一列上, 斜对角线上的偏移量static int count = 0;  //统计多少中放法;/*** 初始化数组,边界上的值用'#'表示, 其余数值用' '表示**/void init(){int i = 0;  //行int j = 0;  //列for(i=0; i < N+2; i++){board[0][i]   = '#';board[N+1][i] = '#';board[i][0]   = '#';board[i][N+1] = '#';}for(i=1; i<=N; i++){for(j=1; j<=N; j++){board[i][j] = ' ';}}}/*** 显示摆放结果**/void display(){int i = 0;int j = 0;for(i=0; i<N+2; i++){for(j=0; j<N+2; j++){printf("%c", board[i][j]);}printf("\n");}}/*** 检测第i行j列上摆放一个女皇是否符合要求**/int check(int i, int j){int ret = 1; //返回值int p = 0;for(p=0; p<3; p++)  //开始在正对角线,列,斜对角线上分别进行检测{int ni = i;int nj = j;while(ret && (board[ni][nj] != '#')){ni = ni + pos[p].i; //坐标偏移量nj = nj + pos[p].j;ret = ret && (board[ni][nj] != 'K');}}return ret;}/***查找第i行摆放女皇的情况**/void find(int i){int j = 0;//如果i已经超出第8行,则表示摆放已经完毕,直接显示摆放结果if(i > N){count++;printf("total: %d\n", count);display();//getchar();}else //还没有摆放结束{for(j=1; j<=N; j++){//检测(i,j)位置处是否可以摆放if(check(i, j)){board[i][j] = 'K';find(i+1); //继续查找下一行的摆放情况 //find(i+1)没有找到正确的摆放状态,回溯到前一状态,然后继续检测(i, j+1)处的摆放是否合法// 或者find(i+1)正确找到了摆放状态,并且已经打印出摆放结果,下面要继续查找另一种摆放方法(i, j+1)是否可行,所以也要回溯到上一状态board[i][j] = ' ';}}}}int main(){init();find(1);return 0;}


 

 

原创粉丝点击