java递归求八皇后问题(所有摆放方式)

本文详细阐述了八皇后问题的解决策略,包括利用栈、哈希表等数据结构进行行、列、斜线的限制判断,通过递归实现棋盘上皇后的位置放置,最终输出所有合法的棋盘布局。

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

        简单说明一下思路。已知一个棋盘,棋子的放置范围为棋盘上的格子,另有四个限制条件:不同行,不同列,不同正斜线,不同反斜线。四个条件中,前两个条件比较简单,随便拿第一个作为先决条件,第二个为尝试条件,两个条件已经固定棋子的位置,所以第三个第四个就可认为是多余条件(就是为了提高问题难度而设置的条件);即放棋子时先看行,一行一个的放,在行中放置过程中尝试不同的列。在行放置过程中检查另外三个条件是否满足,满足就继续放,不满足就回退,尝试。

        前两个条件很好判断。在行从上往下递增列从左到右的坐标系下同一个正斜线上的点行和列的和相等。在行从上往下递增列从右到左递增的坐标系下同以反斜线上的点。和列的和相等。而同一个点的坐标在两个坐标系中很好计算(可以直接看出来)。

下面代码:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
	class Point{
		int x,y;
		public Point(int x,int y ) {
			// TODO Auto-generated constructor stub
			this.x=x;
			this.y=y;
		}
		
		public Point copy(){
			Point point=new Point(x, y);
			return point;
		}
		@Override
		public String toString() {
			return x+","+y;
		}
	}
public class EightQueen {
	
	static int startRow=0;
	static int endRow=7;
	public static void main(String[] args){
		List<Stack<Point>> list=new ArrayList<Stack<Point>>();
		Map<Integer, Integer> rowMap=new HashMap<Integer, Integer>();
		Map<Integer, Integer> colMap=new HashMap<Integer, Integer>();
		Map<Integer, Integer> positiveMap=new HashMap<Integer, Integer>();
		Map<Integer, Integer> negtiveMap=new HashMap<Integer, Integer>();
		Stack<Point> stack=new Stack<Point>();
		placeQueen(list, stack, rowMap, colMap, positiveMap, negtiveMap, startRow, endRow);
		System.out.println(list.size());
		for (Stack<Point> stack2 : list) {
			System.out.println("-----------------------------------------");
			for (Point point : stack2) {
				System.out.println(point);
			}
			
		}
	}
	static int count=0;
	public static int placeQueen(List<Stack<Point>> list,Stack<Point> stack,Map<Integer, Integer> rowMap,Map<Integer, Integer> colMap,Map<Integer, Integer> positiveMap,Map<Integer, Integer> negtiveMap,int currentRow,int aimRow){
		for(int i=0;i<=aimRow;i++){
			Integer countRow = rowMap.get(currentRow);
			Integer countCol=colMap.get(i);
			Integer countP=positiveMap.get(currentRow+i);
			Integer countN=negtiveMap.get(currentRow+aimRow-i);
			if(countRow==null&&countCol==null&&countP==null&&countN==null){
				rowMap.put(currentRow, 1);
				colMap.put(i, 1);
				positiveMap.put(currentRow+i, 1);
				negtiveMap.put(currentRow+aimRow-i, 1);
				if(currentRow==aimRow){
					Point point=new Point(currentRow, i);
					stack.push(point);
					Stack<Point> stack2=new Stack<Point>();
					for(int j=0;j<stack.size();j++){
						stack2.add(stack.get(j).copy());
					}
					list.add(stack2);
					stack.pop();
					rowMap.put(currentRow, null);
					colMap.put(i, null);
					positiveMap.put(currentRow+i, null);
					negtiveMap.put(currentRow+aimRow-i, null);
					return 0;
				}
				Point p=new Point(currentRow, i);
				stack.push(p);
				int result=placeQueen(list, stack,rowMap,  colMap, positiveMap, negtiveMap, currentRow+1, aimRow);
				if(result<1){
					stack.pop();
					rowMap.put(currentRow, null);
					colMap.put(i, null);
					positiveMap.put(currentRow+i, null);
					negtiveMap.put(currentRow+aimRow-i, null);
				}
			}
			
			
			
		}
		
		return -1;
	}
	
}

八皇后问题是经典的回溯算法问题之一,其目标是在8×8的国际象棋棋盘上放置八个皇后,使得它们互不攻击对方。由于皇后的行走规则是横、竖、对角线均可移动任意格数,在解题过程中需要保证每一行、每一列以及每一条斜线上都至多有一个皇后。 ### 使用Java递归解决八皇后问题 #### 核心思想 通过递归来逐行尝试摆放皇后,并检查当前选择是否有效(即是否会与其他已经摆好的皇后发生冲突)。如果某一行无法找到合适的位置,则回退至上一步继续寻找其他可能性;若成功地将所有皇后依次排列完毕,则得到一种可行方案。 #### 实现步骤概述: 1. **创建棋盘**:通常可以利用一维数组`int[] queens = new int[8]`表示整个棋盘的状态。其中下标i代表第(i+1)行,值queens[i]=j 表示该位置放了一个位于(j+1)列上的皇后。 2. **编写验证函数isValid()**: 检查新加入的皇后会不会与之前的所有皇后产生冲突。 3. **编写solveNQueens(int row)** 函数来进行递归解操作: - 当row等于n(这里为8),说明找到了一组满足条件的结果; - 否则从左到右扫描这一行并试着放下皇后,对于每个可能的位置都需要调用 `isValid()` 进行判断; - 如果当前位置合法就进入下一层递归 solveNQueens(row + 1); - 若此路不通(到达叶子节点仍未完成全部填充),应回朔回到前一次状态继续探索其它分支. 4. **输出结果** 下面是基于上述思路的一个简单版JAVA实现代码片段: ```java public class EightQueen { static final int N=8; // 定义棋盘大小 public static void main(String args[]) { int[] result=new int[N]; // 存储最终结果的一维数组 if (placeQueens(result,0)) printResult(result); else System.out.println("No Solution"); } private static boolean placeQueens(int []result ,int row){ if (row==N){return true;} // 找到了完整解决方案 for(int column=0 ;column<N;column++){ if(isValidPlacement(result,row,column)){ result[row]=column; if(placeQueens(result,row+1)) return true ; // 回溯过程... } } return false ; } /** * 判断给定坐标处能否安全放置一个皇后. */ private static boolean isValidPlacement(int []arr,int r ,int c ){ for(int i=0;i<r;++i) if(arr[i]==c || Math.abs(r-i)==Math.abs(c-arr[i])) return false; return true; } /** * 输出棋盘配置情况。 */ private static void printResult(int[] arr) { StringBuilder sb = new StringBuilder(); for (int pos : arr) { char[] chars = new char[arr.length]; Arrays.fill(chars,'.'); chars[pos]='Q'; String str =new String(chars); sb.append(str).append("\n"); } System.out.print(sb.toString()); } } ``` 请注意这个版本只打印第一个遇到的有效布局而忽略了其余的可能性。如果你想要收集所有的非攻击性组合,则可以在每次成功填满棋盘后保存一份深拷贝而不是立即终止程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值