八皇后问题学习探究

版权声明:本文为博主原创文章,未经博主允许不得转载。 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

效率不高,期待以后能够优化

猜你喜欢

转载自blog.csdn.net/qq_35606010/article/details/83310839
今日推荐