引言
由于大学课堂中数据结构中并没有讲一些常见的算法,只是讲的比较简单的定义。所以拿出来暑假时间去研究经典的算法。本文章是研究的八皇后问题。八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。
思路
之前听到过很多次“八皇后问题”,但是都没有仔细研究(好吧,我承认智商不够,精力不足),这次仔细研究了这个问题。首先结合递归的定义,可以分解成相似结构的相同小问题,而这个题因为 每一行 每一列只能能有一个皇后,所以8行可以分解为7行,7行可以分解为6行 ……。这样我们从第一个行开始,如果符合条件,递归调用(raw+1,n,chess);如果raw能到8,则说明是符合的,则打印出来。
说起来比较抽象,上代码看一下:
C语言描述
//山东科技大学小昝
#include <stdio.h>
#include <math.h>
//count 记录一共有多少种符合情况。
int count = 0;
int notDanger(int row,int column,int (*chess)[8]){
int i,j;
for(i=0;i<row;i++){
for(j=0;j<8;j++){
if(chess[i][j]==1){
if(j == column){
return 0;
}
if(abs(i-row) == abs(j-column)){
return 0;
}
}
}
}
return 1;
}
void EightQueen(int row ,int n ,int (*chess)[8]){
int i,j,chess2[8][8];
for(i=0;i<8;i++){
for(j=0;j<8;j++){
chess2[i][j] = chess[i][j];
}
}
if(row == 8){
printf("第 %d 次\n",count+1);
for( i = 0;i <8;i++){
for( j =0 ;j<8;j++){
printf("%d ",*(*(chess2+i)+j));
}
printf("\n");
}
printf("\n");
count++;
}else{
for(i = 0;i<n;i++){
if(notDanger(row,i,chess)){
for(j = 0;j<8;j++){
*(*(chess2+row)+j)=0;
}
*(*(chess2+row)+i)=1;
EightQueen(row+1,n,chess2);
}
}
}
}
int main(){
int chess[8][8],i,j;
for(i=0;i<8;i++){
for(j=0;j<8;j++){
chess[i][j]=0;
}
}
EightQueen(0,8,chess);
printf("一共 %d 种情况!\n",count);
return 0;
}
JAVA描述
package alizantest;
//山东科技大学小昝
public class EightQueen {
static int count = 0;
private static boolean notdanger(int row, int column, int[][] chess) {
// TODO Auto-generated method stub
int i, j;
for (i = 0; i < row; i++) {
for (j = 0; j < 8; j++) {
if (chess[i][j] == 1) {
if (j == column) {
return false;
}
if (Math.abs(row - i) == Math.abs(column - j)) {
return false;
}
}
}
}
return true;
}
private static void EightQueen(int row, int column, int[][] chess) {
int i, j;
int[][] chess2 = new int[8][8];
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
chess2[i][j] = chess[i][j];
}
}
if (row == 8) {
System.out.println("第" + count + 1 + "个");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
System.out.print(chess2[i][j] + " ");
}
System.out.println();
}
System.out.println();
count++;
} else {
for (i = 0; i < column; i++) {
if (notdanger(row, i, chess)) {
for (j = 0; j < 8; j++) {
chess2[row][j] = 0;
}
chess2[row][i] = 1;
EightQueen(row + 1, column, chess2);
}
}
}
}
public static void main(String[] args) {
int[][] chess = new int[8][8];
int i, j;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
chess[i][j] = 0;
}
}
EightQueen(0, 8, chess);
System.out.println("一共有" + count + "种");
}
}
在用java写八皇后的时候犯得一个大的错误,导致费了半小时调试出来的。就是混用了chess与chess2,导致结果不对。所以,我们做事的时候要细心,一定细心!
八皇后问题比较抽象,是经典的算法,多多思考。希望有一天我们都能把递归算法用的炉火存青!