八皇后问题

本文详细介绍了使用递归方法解决八皇后问题,并提供了代码实现。通过模拟棋盘,逐行放置皇后并检测冲突,最终输出所有合法的棋盘布局。文章深入探讨了冲突检测算法,包括行、列、对角线方向的冲突判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天成功加入了importNew翻译小组~就像面试成功了似的~


自己参照着严蔚敏的数据结构书实现了下八皇后问题,递归遍历打印出八皇后棋盘的的所有状态树~


以下是我写的源代码~不知道大家有没有更好的判断一个皇后与已有的皇后有没有冲突的算法呢?


package com.zk.ds;

/**
 * 八皇后问题<br>
 * 算法参见严蔚敏:数据结构(C语言版)P151页
 * @author 1291700520@qq.com
 *
 */
public class EightQueensProblem {
	
	/**
	 * 模拟棋盘,false表示此处没有皇后,true代表此处有皇后
	 */
	private static boolean[][] eightQueens = {
		{false, false, false, false, false, false, false, false},
		{false, false, false, false, false, false, false, false},
		{false, false, false, false, false, false, false, false},
		{false, false, false, false, false, false, false, false},
		
		{false, false, false, false, false, false, false, false},
		{false, false, false, false, false, false, false, false},
		{false, false, false, false, false, false, false, false},
		{false, false, false, false, false, false, false, false},
	};
	
	/**
	 * 统计个数
	 */
	private static int count = 0;
	
	public static void main(String args[]){
		trial(0, eightQueens.length);
	}
	
	/**
	 * 探测棋盘
	 * @param i 当前探测的是棋盘的第几行的索引 i = [0,1,2,...]
	 * @param n n皇后
	 */
	public static void trial(int i, int n){
		if(i >= n){ /*如果所有行检查完毕*/
			System.out.println("--------------" + ++count + "----------------");
			printQueens(eightQueens);
		}else{
			for(int j=0; j<n; ++j){
				eightQueens[i][j] = true; /*进行试探,在eightQueens[i][j]处新放置一个皇后*/
				if(isQueenAvailble(i, j, eightQueens)){ /*如果eightQueens[i][j]不冲突,则继续探测,直至打印*/
					trial(i + 1, n);
				}
				eightQueens[i][j] = false;/*如果eightQueens[i][j]冲突,那么将此皇后移走*/
			}
		}
	}
	
	/**
	 * 如果eightQueens[row][col]处放置一个新的皇后,检测是否有皇后冲突<br>
	 * @param row 新放置的皇后的row
	 * @param col 新放置的皇后的col
	 * @param eightQueens 棋盘
	 * @return 冲突返回false,不冲突返回true
	 */
	private static boolean isQueenAvailble(int row, int col, boolean[][] eightQueens){
		return isRowAvailable(row, col, eightQueens) && isColAvailable(row, col, eightQueens)
					&& isRightSkewAvailable(row, col, eightQueens)
					&& isLeftSkewAvailable(row, col, eightQueens);
	}
	
	/**
	 * 如果eightQueens[row][col]处放置一个新的皇后,检测横线上是否有皇后冲突<br>
	 * @param row 新放置的皇后的row
	 * @param col 新放置的皇后的col
	 * @param eightQueens 棋盘
	 * @return 冲突返回false,不冲突返回true
	 */
	private static boolean isRowAvailable(int row, int col, boolean[][] eightQueens){
		for(int j=0; j<eightQueens.length; ++j){
			if(eightQueens[row][j] && j != col){
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 如果eightQueens[row][col]处放置一个新的皇后,检测竖线上是否有皇后冲突<br>
	 * @param row 新放置的皇后的row
	 * @param col 新放置的皇后的col
	 * @param eightQueens 棋盘
	 * @return 冲突返回false,不冲突返回true
	 */
	private static boolean isColAvailable(int row, int col, boolean[][] eightQueens){
		for(int i=0; i<eightQueens.length; ++i){
			if(eightQueens[i][col] && row != i){
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 如果eightQueens[row][col]处放置一个新的皇后,检测右对角线上是否有皇后冲突<br>
	 * @param row 新放置的皇后的row
	 * @param col 新放置的皇后的col
	 * @param eightQueens 棋盘
	 * @return 冲突返回false,不冲突返回true
	 */
	private static boolean isRightSkewAvailable(int row, int col, boolean[][] eightQueens){
		int rows = eightQueens.length;
		int whichMin = (row <= col) ? -row : -col;
		int whichMax = (rows - row) <= (rows - col) ? (rows - row) : (rows - col);
		for(int i=whichMin; i<whichMax; ++i){
			if(eightQueens[row + i][col + i]){
				if(i != 0){
					return false;
				}
			}
		}
		return true;
	}
	
	/**
	 * 如果eightQueens[row][col]处放置一个新的皇后,检测左对角线上是否有皇后冲突<br>
	 * @param row 新放置的皇后的row
	 * @param col 新放置的皇后的col
	 * @param eightQueens 棋盘
	 * @return 冲突返回false,不冲突返回true
	 */
	private static boolean isLeftSkewAvailable(int row, int col, boolean[][] eightQueens){
		int maxIndex = eightQueens.length - 1;
		int leftOffset = 0;
		int rightOffset = 0;		
		if(row + col <= maxIndex){/*所探测的点位于左上半部分*/
			leftOffset = -col;
			rightOffset = row;
		}else{/*所探测的点位于右下半部分*/
			leftOffset = row - maxIndex;
			rightOffset = maxIndex - col;
		}
		
		for(int i=leftOffset; i<=rightOffset; ++i){
			if(eightQueens[row - i][col + i] && i != 0){
				return false;
			}
		}		
		return true;
	}
	
	/**
	 * 打印当前棋牌<br>
	 * [*]表示有皇后,[ ]表示无皇后
	 * @param eightQueens
	 */
	private static void printQueens(boolean[][] eightQueens){
		for(boolean[] b1:eightQueens){
			for(boolean b2:b1){
				if(b2){
					System.out.print("[*],");
				}else{
					System.out.print("[ ],");
				}
			}
			System.out.println();
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值