版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35606010/article/details/83310839
八皇后问题学习探究
在学习过程中发现了这个问题,自己深入理解和探究的过程中产生了代码,以博客形式记录下来当时的思路。本文旨在记录学习内容以便在未来的工作中能够更好的提升自己,如果能为他人提供一种思路,是我的荣幸。
- 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。
- 该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:
- 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
- 高斯认为有76种方案, 1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
目录
模拟棋盘:
以二维数组array[y][x]作为一个棋盘承载棋子0为空,1为放置皇后
下图为其中一种摆放方法,以作参考
\x 0 1 2 3 4 5 6 7
y\
0 0 0 0 0 0 0 0 1
1 0 0 1 0 0 0 0 0
2 1 0 0 0 0 0 0 0
3 0 0 0 0 0 1 0 0
4 0 1 0 0 0 0 0 0
5 0 0 0 0 1 0 0 0
6 0 0 0 0 0 0 1 0
7 0 0 0 1 0 0 0 0
代码+注释:
package priv.wcz.eightQueen.first;
import java.util.Date;
/**
* 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。
* 该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:
* 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
* 高斯认为有76种方案。
* 1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
*/
/**
* @Description
* @Author wcz
* @Date 2018-10-22 17:42
**/
public class EightQueen {
// 王后数量,对应棋盘长宽 设置为8符合题意
private static int NUM_OF_QUEEN = 8;
// 空格
private static int FLAG_OF_NULL = 0;
// 放置王后
private static int FLAG_OF_QUEEN = 1;
private static int count = 0;
private static void putQueueAtRow(int[][] chess ,int row){
// 当处理到第八行时输出结果,输出二维棋盘会严重影响计算效率
if(row == NUM_OF_QUEEN){
count++;
// System.out.println("===================================================");
// for(int i=0;i<NUM_OF_QUEUE;i++){
// for(int j=0;j<NUM_OF_QUEUE;j++){
// System.out.print(chess[i][j]+" ");
// }
// System.out.println();
// }
// System.out.println("第"+count+"种解法");
// System.out.println("===================================================");
return;
}
// 每次要处理下一行时复制当前的棋盘数组
int chessTemp[][] = chess.clone();
// 处理当前行的摆放情况
for(int i=0;i<NUM_OF_QUEEN;i++){
// 先将当前行全部置空
for(int j=0;j<NUM_OF_QUEEN;j++){
chessTemp[row][j] = FLAG_OF_NULL;
}
// 依次放置王后
chessTemp[row][i] = FLAG_OF_QUEEN;
// 当行数不大于棋盘宽高 并且 放置位置安全
if(row < NUM_OF_QUEEN && isSafety(chessTemp,row,i)) {
putQueueAtRow(chessTemp,row+1);
}
}
}
/**
* 判断放置位置是否安全
* 放置顺序从上到下,从左到右,每一个棋子在放置的时候,危险只可能来自该棋子所属行数上方
* 即考虑左上135°的直线上,垂直90°直线上,右上45°直线上
* 是否有棋子
* @param chess
* @param row
* @param col
* @return
*/
private static boolean isSafety(int[][] chess, int row, int col){
// 移动步数
int t = 1;
while(t <= NUM_OF_QUEEN){
// 左上
if(row-t>=0 && col-t>=0 && chess[row-t][col-t] == FLAG_OF_QUEEN){
return false;
}
// 中上
if(row-t>=0 && chess[row-t][col] == FLAG_OF_QUEEN){
return false;
}
// 右上
if(row-t>=0 && col+t<NUM_OF_QUEEN && chess[row-t][col+t] == FLAG_OF_QUEEN){
return false;
}
t++;
}
return true;
}
public static void main(String[] args) {
Date begin =new Date();
// 以二维数组描述一个N*N的棋盘
int[][] chess=new int[NUM_OF_QUEEN][NUM_OF_QUEEN];
// 初始扫描行数
int row = 0 ;
// 开始计算结果
new EightQueen().putQueueAtRow(chess,row);
Date end =new Date();
System.out.println(NUM_OF_QUEEN+ " 皇后问题,用时:" +String.valueOf(end.getTime()-begin.getTime())+ "毫秒,结果总计:"+count);
}
}
运行结果:
8 皇后问题,用时:15毫秒,结果总计:92
效率不高,期待以后能够优化