算法-N皇后(回溯)

import java.util.Scanner;

/**
皇后是国际象棋中威力最大的棋子。在下面所示的棋盘上,皇后可以攻击位于箭头所覆盖位置的所有棋子。
我们能不能把N个皇后放在棋盘(N×N)上,它们中的任何一个都无法攻击其余的皇后,即任两个皇后不能在同一行,同一列或者同一对角线上。
请编写程序输出皇后的摆放方案,并找出一共有几种方法。
 * @author Vivinia
 *
 */
public class NQueen {
	static int count=0;
	static int N=0;
	static int[][] Q;
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		N=input.nextInt();
		Q=new int[N][N];
		input.close();
		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
				Q[i][j]=0;
		Queen(0);     //从第1行开始,放第一个皇后
		System.out.println("The number of the answer are "+count);
	}

	private static void Queen(int k) {
		if(k==N) {               //递归结束
			for(int i=0;i<N;i++) {
				for(int j=0;j<N;j++)
					System.out.print(Q[i][j]+" ");
				System.out.println();
			}
			System.out.println();
			count++;
			return;       //这也是退出的一种方式,所以不管找到没找到解,都要回溯进行下一次查找
		}
		for(int j=0;j<N;j++) {    //4个皇后乃没有放完
			if (isCorrect(k,j)) {    //如果Q[i][k]可以放 皇后
				Q[k][j]=1;   //放皇后
				Queen(k+1);   //递归检索下一行的位置
				Q[k][j]=0;   //回溯到上一层(如果下一行没有找到合适的位置,则执行完退回执行该语句,如果找到合适的点,会一直递归,知道找到解)
			}
		}
	}

	private static boolean isCorrect(int i, int j) {     //判断行,列,两条对角线
		int s,t;
		for(s=i,t=0;t<N;t++)      //判断行
			if(Q[s][t]==1&&t!=j)
				return false;
		for(t=j,s=0;s<N;s++)          //判断列
			if(Q[s][t]==1&&s!=i)
				return false;
		for(s=i-1,t=j-1;s>=0&&t>=0;s--,t--)      //判断左上方
			if(Q[s][t]==1)
				return false;
		for(s=i-1,t=j+1;s>=0&&t<N;s--,t++)       //判断右上方
			if(Q[s][t]==1)
				return false;
		return true;
	}
}

之前曾经N皇后的例子,但那是根据老师的算法写的,感觉思路不是很清晰。今天修改了判断部分的代码,可能比之前那个繁琐了些,但是我觉得更容易理解。

回溯之类的算法我一直不怎么会用,通过这个例子我才似乎明白了,不需要额外设置什么变量保存上一个放皇后的位置,因为回溯是基于递归的,而递归都是通过栈来实现的,所以当你重新递归一次时,会在栈中保存你当前的变量。到最后不管你是查询失败return的还是查询成功return的,都会重新回到这个位置取出栈中元素。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值