算法编程(JAVA)--八皇后问题

本文介绍了一种解决经典的八皇后问题的方法,通过递归和回溯算法,在8×8的棋盘上放置八个皇后,确保它们互不攻击。使用二维数组记录棋盘状态,详细解释了如何判断和更新皇后的位置及其影响范围。

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

题目:在一个8×8国际象棋盘上,有8个皇后,每个皇后占一格;
要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行、同一列或同一对角线上。

问共有多少种不同的方法?

解题思路:通过一个int[8][8]的二位数组构建棋盘,初始化为0,我们可以定义如果该位置摆放了皇后那么该位置对应的二维数组被置为-1。因为皇后之间不能相互攻击,所以我们要明确指出该皇后的影响范围,于是我们采用将该皇后能影响到的棋盘位置全部+1,比如:

-11111111
11000000
10100000
10010000
10001000
10000100
10000010
10000001

这样我们就可以判断,只要是0的地方就可以放置皇后,只要是-1就是皇后的位置,只要是大于0的地方就是被皇后影响的地方。这样做有个什么好处呢,就是我们再回溯时只需要通过简单的对皇后的影响范围进行-1就可以取消她的影响范围了。下面直接贴出代码,后面有注释。如果读者有什么疑惑可以给我留言~~

<pre name="code" class="java">public class Main {
	static int[][] Arr = new int[8][8];
	static int Count=0;
	
	public static void main(String[] args){
		Cal(0,0);//递归函数,传入当前选中位置是第几行第几列
		System.out.println(Count);
	}
	public static void Cal(int a,int b){
		if(a==8){
			Count++;
			for(int j=0;j<8;j++){//寻找第8行已经摆放了的皇后的位置
				if(Arr[7][j]==-1){
					Sub(7,j);//找到后拿掉皇后,并且取消掉该皇后的影响
					return;
				}
			}
		}
		else{
			boolean Flag=true;//设置一个标志位,用来判断该行是否还有可以摆放皇后的位置
			for(int i=0;i<8;i++){
				if(Arr[a][i]==0){
					Flag=false;//若有可以摆放皇后的位置,将标志位置为false
					Add(a,i);//摆放这个皇后,并且添加该皇后的影响
					Cal(a+1,i);//将下一个状态带入状态方程
				}
			}
			if(Flag==true){//如果没有找到可以摆放皇后的位置,就取消掉上一层的皇后的位置,并且消除该皇后的影响
				Sub(a-1,b);
				return;
			}
			if(Flag==false&&a>0){//如果有改层有可以摆放皇后的位置,就要在回溯时拿掉该皇后,并且取消该皇后的影响
				for(int i=0;i<8;i++){
					if(Arr[a-1][i]==-1){
						Sub(a-1,i);
						return;
					}
				}
			}
			return;
		}
		
	}
	public static void Add(int x,int y){//添加皇后,并且添加该皇后的影响
		Arr[x][y]=-1;
		for(int i=0;i<8;i++){
			if(i!=y)
			Arr[x][i]=Arr[x][i]+1;
		}
		for(int i=0;i<8;i++){
			if(i!=x)
			Arr[i][y]=Arr[i][y]+1;
		}
		for(int i=-7;i<8;i++){//左上到右下
			if((i+x)>=0&&(i+x)<8&&i!=0&&(i+y)>=0&&(i+y)<8){
				Arr[x+i][y+i]=Arr[x+i][y+i]+1;
			}
		}
		for(int i=-7;i<8;i++){//左下到右上
			if((x-i)>=0&&(x-i)<8&&i!=0&&(i+y)>=0&&(i+y)<8){
				Arr[x-i][y+i]=Arr[x-i][y+i]+1;
			}
		}
	}
	public static void Sub(int x,int y){//消去该皇后的影响
		Arr[x][y]=0;
		for(int i=0;i<8;i++){
			if(i!=y)
			Arr[x][i]=Arr[x][i]-1;
		}
		for(int i=0;i<8;i++){
			if(i!=x)
			Arr[i][y]=Arr[i][y]-1;
		}
		for(int i=-7;i<8;i++){//左上到右下
			if((i+x)>=0&&(i+x)<8&&i!=0&&(i+y)>=0&&(i+y)<8){
				Arr[x+i][y+i]=Arr[x+i][y+i]-1;
			}
		}
		for(int i=-7;i<8;i++){//左下到右上
			if((x-i)>=0&&(x-i)<8&&i!=0&&(i+y)>=0&&(i+y)<8){
				Arr[x-i][y+i]=Arr[x-i][y+i]-1;
			}
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值