回溯法经典例题(五):java解n皇后问题

n皇后问题

问题描述

如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击
皇后彼此之间会产生攻击是在情况如下:

  • 同一行
  • 同一列
  • 同一斜线上

定义解空间

由题,放置时可以按行的顺序确定列的位置来放置皇后,如四皇后问题,就总共有四个皇后,那么,第一行的皇后可以放在1、2、3、4列,既由根结点往下有四个子结点,接着第二行的皇后同样也有四个选择,则可判断该问题的解空间就是按行的顺序确定列的位置。

确定解空间结构

由上一个解空间的解释可以确定此次的思路是一棵子集树

剪枝函数

用xi表示皇后i放在棋盘的第i行的第xi列, xj表示皇后j放在棋盘的第j行的第xj列。
由于不允许将2个皇后放在同一行所以:i≠j
由于不允许将2个皇后放在同一行所以:xi ≠ xj
由于2个皇后不能放在同一斜线上,即不处于同一正、反对角线,所以:|i-j|≠|xi-xj|

代码实现

package nQueensProblem;
import java.util.Scanner;
public class NQP {
	static int n;//皇后个数
	static int[] x;//当前解;x[i]表示第i行的皇后i所处的列号
	static int sum;//可行解个数
	public static int nqueens(int nn) {
		n=nn;
		x=new int[n+1];
		for(int i=0;i<=n;i++) x[i]=0;
		sum=0;
		backtrack(1);
		return sum;
	}
	public static void backtrack(int t) {
		if(t>n) {
			sum++;
			for(int i=1;i<=n;i++) {
				if(i==n)
					System.out.println(x[i]);
				else
					System.out.print(x[i]+" ");
			}
		}
		else {
			for(int i=1;i<=n;i++) {
				x[t]=i;//是x[t]不是x[i]
				if(place(t))
					backtrack(t+1);
			}
		}
	}
	public static boolean place(int k) {
		for(int j=1;j<k;j++) {//是j
			if(x[j]==x[k]||(Math.abs(j-k)==Math.abs(x[j]-x[k])))
				return false;
		}
		return true;
	}
	public static void main(String[] args) {
		System.out.print("请输入皇后的个数:");
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		System.out.println("即可行解有以上"+nqueens(n)+"种");
	}
}

你可能感兴趣的:(算法,回溯法)