八皇后问题及n皇后问题解法及效率优化笔记(1)

八皇后问题是一个很有趣的问题,话说,有一个八行八列的棋盘,有八个皇后棋子,这八个棋子摆在这八行八列的棋盘上,且行列斜线都不能重合,由此,推及到n皇后问题。

八皇后的程序效率问题是一个相当值得研究的问题,程序效率的高低和程序算法密切相关,由此,研究程序效率最后变成了算法的研究。有人将类似追求效率极致的编程称为极限编程。

一个问题的解法千千万,但效率最好的却不好发现。

下面,是我关于八皇后及n皇后问题解法的第一版,初始版,也为了循序渐进,效率不高,代码没有使用多线程,全靠一个主线程在浪!

代码如下:

/****
 * 八皇后问题解法(皇后 不同行 不同列 不同斜线)
 * 
 * @author wjw
 *
 * @since 2018-03-14
 */
public class EightQueenQuestion {

	private static final int HAS_CHESSMAN = 1;//有皇后棋子标志
	private static final int NO_CHESSMAN = 0;//无皇后棋子标志
	
	//初始化全局计数器
	private static long count = 0;
	
	public static void main(String[] args) {
		//初始化棋盘(从8皇后)
		int n = 8;
		for (int i = n; i < 20; i++) {
			long beginTime = System.currentTimeMillis();
			int[][] chessBoard = initChessBoard(i);
			setChessBoard(chessBoard,0);
			System.out.println(i + "皇后问题共有符合条件排列方式  " + count + "种,耗时" + (System.currentTimeMillis() - beginTime) + "ms");
			count = 0;//计数器归0
		}
	}
	
	/*****
	 * 初始化空棋盘
	 * @param n
	 * @return
	 */
	public static int[][] initChessBoard(int n){
		int[][] chessBoard = new int[n][n];
		
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				chessBoard[i][j] = NO_CHESSMAN;
				
			}
			
		}
		return 	chessBoard;
		
	}
	
	/******
	 * 设置棋盘棋子位置 + 检验棋子位置是否合格
	 * @param chessBoard
	 * @param line
	 * @return
	 */
	public static void  setChessBoard(int[][] chessBoard, int line){
		for(int i = 0; i < chessBoard.length; i++) {
			chessBoard[line][i] = HAS_CHESSMAN;
			if(line == chessBoard.length -1){
				if(check(chessBoard)){
					//printQueue(chessBoard);
					count++;
				}
				
			}else{
				setChessBoard(chessBoard, line + 1);
			}
			_refreshHorizontal(chessBoard, line);
		}
		
	}
	
	
	
	/******
	 * 检验当前n皇后排列方式是否合格
	 * @param queue n皇后排列方式
	 * @return
	 */
	public static boolean check(int[][] queue){
		int n = queue.length;
		long horizontalResult = 0;
		long verticalResult = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				
				
				//左右不同斜线
				if(queue[i][j] == HAS_CHESSMAN){
					/*****
					 * 验证左斜线
					 * *     
					 * *     
					 * ******
					 */
					if(j > 0 && i < n - 1){
						if(!_leftCompare(i, j, queue))
							return false;
					}
					
					
					
					/*****
					 * 验证右斜线
					 *      *     
					 *      *     
					 * ******
					 */
					if(j < n - 1 && i < n -1){
						if(!_rightCompare(i, j, queue))
							return false;
					}
					
				}
				
				//分别计算横纵向和
				horizontalResult += queue[i][j];
				verticalResult += queue[j][i];
				//横向结果或纵向结果和大于1,表示该行有多于一个皇后,不符合条件
				if(horizontalResult > 1 || verticalResult > 1){
					return false;
				}
			}
			//换行归0
			horizontalResult = 0;
			verticalResult = 0;
		}
		
		
		
		
		
		
		
		return true;
		
	}
	
	/******
	 * 递归左比较
	 * @param i
	 * @param j
	 * @param queen
	 * @return
	 */
	private static boolean _leftCompare(int i,int j, int[][] queue){
		if(j == 0 || i == queue.length -1){
			//左比较,比较到最左边或最下边仍然没有棋子,返回true
			return true;
		}
		if(queue[i+1][j-1] == HAS_CHESSMAN)
			return false;
		return _leftCompare(i+1, j-1, queue);
		
		
	}
	
	/******
	 * 递归右比较
	 * @param i
	 * @param j
	 * @param queen
	 * @return
	 */
	private static boolean _rightCompare(int i,int j, int[][] queen){
		if(i == queen.length - 1 || j == queen.length - 1){
			//右比较,比较到最右边或最下边仍然没有棋子,返回true
			return true;
		}
		if(queen[i+1][j+1] == HAS_CHESSMAN)
			return false;
		return _rightCompare(i+1, j+1, queen);
		
		
	}
	
	
	/*****
	 * 排列组合计算共有多少种排列方式
	 * @param n
	 * @return
	 */
	public static long chessBoardNum(int n){
		long tempUpNum = 1;
		long tempDownNum = 1;
		for (int i = 0; i < n; i++) {
			tempUpNum *= n * n - i;
			tempDownNum *= n - i;
		}
		return tempUpNum / tempDownNum;
	}
	
	/****
	 * 恢复棋盘第n行
	 * @param chessBoard
	 * @param n 待恢复复行数
	 */
	private static void _refreshHorizontal(int[][] chessBoard, int n){
		
		for (int i = 0; i < chessBoard.length; i++) {
			chessBoard[n][i] = 0;
		}
		
	}
	
	/*****
	 * 打印当前棋盘
	 * @param chessBoard
	 */
	public static void printQueue(int[][] chessBoard){
		
		int n = chessBoard.length;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				System.out.print(chessBoard[i][j] + "    ");
				
			}
			System.out.println("\r\n");
		}
		System.out.println("\r\n");
	}
}

运行结果如下:

8皇后问题共有符合条件排列方式  92种,耗时899ms
9皇后问题共有符合条件排列方式  352种,耗时22073ms

10皇后问题共有符合条件排列方式  724种,耗时694752ms


从运行结果看,效率很慢,第一版,为以后提供了很大的优化空间啊

待续...

如有错误,欢迎指正

end

猜你喜欢

转载自blog.csdn.net/wjw521wjw521/article/details/79555541