您的位置:首页 > 其它

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

2016-04-27 22:09 330 查看
题目描述

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如今有一个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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: