八皇后问题求解

国际象棋中,若皇后出现在同一条直线或者斜线上,就会被一方吃掉,

怎样才能在一个棋盘上放下八个皇后,就是八皇后问题。

 

 

0

1

2

3

4

5

6

7

7

 

 

 

 

 

 

 

Q

6

 

 

 

 

 

Q

 

 

5

 

 

 

Q

 

 

 

 

4

 

Q

 

 

 

 

 

 

3

 

 

 

 

 

 

Q

 

2

 

 

 

 

Q

 

 

 

1

 

 

Q

 

 

 

 

 

0

Q

 

 

 

 

 

 

 

 

① Col[] :存 1 表示某列有皇后

 

 

 

 

 

 

 

 

  0    1     2     3    4    5     6    7 

 

② Left[](left = i + j): 存 1 表示某左斜线上有皇后

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

   0    1     2    3    4     5     6    7   8    9    10   11  12  13  14

 

③ Right[] ( right = i - j + 7 ):存 1 表示某右斜线上有皇后

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

   0    1     2    3    4    5    6     7    8     9   10   11  12  13  14

 

④ Q[] :用栈来存放每个皇后的坐标位置,回溯时栈顶指针出栈

1

3

5

7

2

4

6

8

行     0     1    2    3    4    5    6    7

 

 

寻找一个解的过程:

1.皇后栈不满时,依次在每一行的每一列找是否存在一个位置可以放下一个皇后。

2.如果可以将该位置存入皇后栈,并且更新棋盘状态(col,left,right),然后跳到下一行继续探查。

3.否则回到上一行,将皇后栈中最后存入的皇后位子出栈,将棋盘的状态回调到上一个状态,从该位置的后面继续找可以放下皇后的位置。

4.直到皇后栈存满时,找到一组解,输出棋盘状态。

 

代码思路:

While(皇后栈不满时){

    for( 遍历所有列 ){

        if(如果该位置满足条件){

             更新棋盘状态;

             i ++;j = 0; //跳到下一行的第一列,继续寻找合适的位置

             break跳出for循环;

         }

    }

    if(j==8){ //该行没有找到合适的位置,说明上一行的皇后位置不合适,需要改变

          i--;j = Q[top--]; //回到栈顶皇后的位置;

          将棋盘的状态回调到上一个状态;

          j ++  从栈顶皇后的后一个相邻位置继续寻找;

      }

}

 

 

回溯都可以用递归求解

 

递归求所有解代码思路:

 

void  Queen(int i){

         for( int  j = 0; j < 8; j++){

                if((i,j)位置满足条件){

                      皇后放入数组;

                      修改棋盘状态;

                      if(i < 7){ //8个皇后还没找完

                            递归调用Queen( i+1 )函数,跳至下一行继续递归寻找

                      }else{ //找完8个皇后

                             输出棋盘状态

                    }

                    若上一行寻找失败,或者输出完一组解后,将棋盘状态回调一次(left,right,col);

               }

          }

    //return  若本行没有找到满足条件的位置,返回上一次递归调用点

}

 

递归求所有解的代码实现

#include<stdio.h>

int cnt = 0;            //输出时记录状态数
int col[8] = {0};        //记录每一行中是否存有皇后  
int left[15] = {0};        //记录每一左斜线中是否存有皇后
int right[15] = {0};    //记录每一右斜线中是否存有皇后
int Q[8] = {0};         //皇后栈,记录依次进栈的每个皇后的列位置

//数组在初始化时,如果初始化了第1个字符,后面的字符,系统会自动填充为0,这是一个C语言中的规定。
//统一赋值的方法: memset(arrName, 'M', sizeof(arrName));

//输出
void Print(int Q[]){
        
    printf("\n第%d种棋盘状态:\n\n",++cnt);
    printf("*****************\n");
    for(int i = 7; i > -1; i--){
        printf("|");
        for(int j = 0; j < 8; j++){
            if(j == Q[i])
                printf("Q|");
            else
                printf("X|");
        }
        printf("\n");
    }
    printf("*****************\n");
}

void Queen(int i){

    for(int j = 0; j < 8; j++){    //在某行中找可以放下皇后的位置
        if((!col[j]) && (!left[i+j]) && (!right[i-j+7])){    //如果第i行第j列满足放下皇后的条件
            //更新棋盘状态
            col[j] = 1;
            left[i+j] = 1;
            right[i-j+7] = 1;
            Q[i] = j;        //把皇后放下
            if(i < 7){        //如果8个皇后还没找完则
                Queen(i+1);     //递归,跳至下一行继续递归寻找                             
            }
            else{            //找完8个皇后即求得一组解,将其输出
                Print(Q);
            }
            //若上一行寻找失败,或者输出完一组解后,将棋盘状态回调一次
            col[j] = 0;
            left[i+j] = 0;
            right[i-j+7] = 0;
        }
    }
    //return  本行没有找到满足条件的位置,返回上一次递归调用点
    
}

int main(void){
    printf("递归求解八皇后问题\n");    
    Queen(0);
    printf("\n以上是求得所有解\n");         
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值