您的位置:首页 > 其它

《算法设计与分析》八皇后问题

2019-07-17 11:15 197 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_40903237/article/details/96277691

1、题目描述:在8x8的国际象棋上面摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行,同一列或者同一条斜线上,请问有多少种摆法?

当时高斯先生计算说有76种,但是最后有92种。

2、代码解析(递归) 

步骤:分解为两个子问题,首先在第一行放置一个棋子,第二在其他安全的不被攻击的地方放第二个棋子,以此类推。

结束条件:放完第八个棋子就结束了。

[code]package com.yuanfeng.test;/**
* Created by yuanfeng on 2019/7/17 10:12
*/

/**
*@ClassName EightQueen
*@Description T0D0
*@Author yuanfeng
*@Date 2019/7/17 10:12
*@Version 1.0
**/
public class EightQueen {

//定义一个变量计算种数
private static int count = 0;

/*
*
* @Author yuanfeng
* @Description //TODO
* @Date 10:32 2019/7/17
* @Param [row, j, chess]chess传进来的棋盘
* @return int
**/
public static int security(int row,int j,int[][]chess){

int i = 0,flag1 = 0,flag2= 0,flag3=0,flag4=0,flag5=0,k;
//判断列方向的危险
for(i = 0;i<8;i++){
if(chess[i][j] != 0){
flag1 = 1;
break;
}
}
//判断左上方,因为代码不好直接判断啊一条斜线
for (i = row,k = j;i>=0 && k>=0;i--,k--){
if(chess[i][k] != 0){
flag2 = 1;
break;
}
}
//判右下方,因为代码不好直接判断啊一条斜线
for (i = row,k = j;i<8 && k<8;i++,k++){
if(chess[i][k] != 0){
flag3 = 1;
break;
}
}

//判断右上方,因为代码不好直接判断啊一条斜线
for (i = row,k = j;i>=0 && k<8;i--,k++){
if(chess[i][k] != 0){
flag4 = 1;
break;
}
}
//判断左下方,因为代码不好直接判断啊一条斜线
for (i = row,k = j;i<8 && k>=0;i++,k--){
if(chess[i][k] != 0){
flag5 = 1;
break;
}
}

if(flag1 == 1 || flag2 == 1 || flag3 == 1 || flag4 == 1 || flag5 == 1){
return 0;
}else {
return 1;
}

}
/*
*
* @Author yuanfeng
* @Description //TODO
* @Date 10:22 2019/7/17
* @Param [row, col, chess]chess代表指向每一行的指针
* @return void
**/
//参数为row,col,指向棋盘的引用

public static void eightQueen(int row,int col,int[][] chess){

//建立一个临时棋盘来存放最后要打印的92个棋盘
int[][] chess2 = new int[8][8];
int i,j;
//主棋盘赋值给临时的棋盘
for( i = 0;i < chess2.length;i++){

for (j = 0;j < chess2[0].length;j++) {

chess2[i][j] = chess[i][j];
}
}

//递归结束条件,row==8已经到了第九行了,代表前面已经结束了
if(row == 8){
count=count+1;
System.out.println("第"+count+"种");
for(i = 0;i<8;i++){
for( j = 0;j<8;j++){
System.out.print(chess2[i][j]);
}
System.out.println();//换行
}
System.out.println();
}else {

//不符合条件的时候,判断这个位置是否有攻击危险
//如果没有危险。继续往下
//每一行一格一格往下判断

for(j = 0;j<col;j++){
//判断是否危险
if(security(row,j,chess) == 1){

for(i = 0;i<8;i++){
chess2[row][i] = 0;//整行所有列的值赋值为0
}
chess2[row][j] = 1;//不危险的j的位置赋值为1
//接着下一行递归测试
eightQueen(row+1,col,chess2);
}
}
}
}
public static void main(String[] args) {

//定义一个二维数组来表示8x8的棋盘
int chess[][] = new int[8][8];

//棋牌所有初始化为0
for(int i = 0;i < chess.length;i++){
for (int j = 0;j < chess[0].length;j++){
chess[i][j] = 0;
}
}

eightQueen(0,8,chess);
System.out.println("总共有"+count+"种解决方法");
}

}

 

总结:

说说大体的思路,本身这个题目中我们首先将一个二维数组棋盘赋值为0,目的是最后1是代表的皇后。

递归进入eightQueen()的时候,最开始row是不满足row == 8这个条件的,所以这个时候进行else判断,定义一个security方法判断row行j列的元素是否安全,整行赋值0,安全的位置赋值1,row+1进行下一行的递归。

其中security这个方法是判断该皇后位置的左上方,右下方,左下方,右上方的位置是否存在冲突。

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: