【算法训练】八皇后问题回溯算法求解

题目描述
会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如今有一个8*8的棋盘,如何将 8 个皇后放在棋盘上,使它们谁也不能被吃掉!这就是著名的八皇后问题。

分析:这个问题在求解时可以使用回溯算法去分析问题——在第一行放上棋子以后,递归到第二行,找到一个能放置棋子的位置,将棋子放上后,递归到第三行。。 。。。 依次类推,但是会找到一行,没有办法放置棋子,也就是说,放置位置上,行、列、斜线都已经有棋子了,那么这时就要返回到上一步,重新放置上一步的棋子,再走下一步,直到下一步能放置棋子便好。整个棋盘放好的标志是第八行已经放置了棋子。


使用回溯算法思考后,思路就很清晰了,虽然这个算法时间复杂度不低,但是它属于那种很好理解的思路,代码如下:


#include<stdio.h>
#include<stdlib.h>
//首先定义几个全局的数组来当作存放皇后的标志位
int cnt=0;          //cnt 用来计算解的个数
int col[8]={0};     //数组col 用来标志本行的某列是否存放了皇后
int left[15]={0};   //数组left用来标志该位置的左对角线是否放置皇后
int right[15]={0};  //数组right 作用同上
int Q[8]={-1};      //数组Q用来存放最后的结果

//当第八个皇后放置完成后,输出这个解
void PrintQueen()
{
    printf("\n第%d个解:\n",++cnt);
    for(int i=0;i<8;++i){
        for(int j=0;j<8;++j){
            if(Q[i]==j)
                printf("Q  ");
            else
                printf("x  ");
        } 
        printf("\n");
    }       

}

//放置皇后(回朔+贪心)
void Queen(int i){
    for(int j=0;j<8;++j){
        if(col[j]==0&&left[i+j]==0&&right[7+i-j]==0){   //判断每一列 每条斜线(左右斜线)是否都无棋子是则放置皇后
            Q[i]=j;                                     //Q[]数组存放这一行的有皇后列数
            col[j]=left[i+j]=right[7+i-j]=1;            //放好以后全部置1,表示这一列,这一左右对角线都不能再放置皇后
            if(i<7) 
                Queen(i+1); //如果皇后还没有放置在最后一行,那么递归调用放置皇后
            else{
                PrintQueen();//否则,说明皇后放置完成,就输出它
            }

            //抹掉这个位置的皇后,后重新摆放
            Q[i]=-1;
            col[j]=left[i+j]=right[7+i-j]=0;
        }
    }
}

int main(void){
    Queen(0);
    return 0;
}
发布了31 篇原创文章 · 获赞 17 · 访问量 4万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览