基本概念
编程思想
对于这样一个问题我们首先想是要创建一个8x8格式的棋盘,我们用二维数组去实现,数组中的每个值初始化为0,用值1表示这个地方已经放了棋子。这样我们每一行都用一个1来表示放了一个棋子。
问题的关键在于递归回溯,和判断某一位置是否这一放置棋子。当我们在某一位置想要放置棋子时我们要先判断这个位置是否和上面的棋子在同一条线上,如果不在同一条线上就标志1,如果在就向后一个位置判断,假如整行都不符合条件那就向上回溯了,到了上面一行我们将标志位向后移动一位继续开始向下的递归。
代码解读
代码共有三个函数组成:print()打印棋盘,check()判断是否满足条件,EightQueen()算法总函数。
对于算法的复杂度分析:
由于算法是会回溯的它会尝试每种情况
最多的情况有 8 * 8 * 8 * 8 * 8 * 8 * 8 * 8 即 8^8
程序会最多尝试8^8次数
算法复杂度为:O(n^8)
typedef int Status;
int count;//共有多少种放置方法
int a[8][8];//棋盘
//打印二位棋盘
void print(){
int i,j;
printf("第%d方案",count);
printf("\n\n");
for(i=0;i<8;i++){
for(j=0;j<8;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
}
Status check(int r,int c){
//r: 行标志
//c: 列标志
int index;
//遍历行,检查这个位置的垂直方向
for(index=0;index<r;index++){
//如果检测到垂直方向有了放置的棋子,返回0
if(a[index][c]){
return 0;
}
}
int k,j;
//检测左上斜线
for(k=r-1,j=c-1;k>=0&&j>=0;k--,j--){
if(a[k][j]){
return 0;
}
}
//检测右上斜线
for(k=r-1,j=c+1;k>=0&&j<=7;k--,j++){
if(a[k][j]){
return 0;
}
}
//如果都满足条件,返回1
return 1;
}
void EightQueen(int row){
//row的作用:递归每一行
//当row为8时即超出数组行标数,说明一种情况产生,打印返回
if(row==8){
count++;//有多少种情况
print();//打印棋盘
return;
}
int c;
//遍历每一列
for(c=0;c<8;c++){
//如果满足放置条件
if(check(row,c)){
a[row][c]=1;
//进行下一行的判断
EightQueen(row+1);
//回溯:当递归返回时说明下一行不满足放置条件
//将此位置0,也就是拿走棋子,向下一个满足条件的位置放置
a[row][c]=0;
}
}
}
执行结果
由此可见八皇后问题共有92种解法
对此我们可以延伸出N皇后的问题
不过主要还是对于递归和回溯思想的应用