回溯法--n皇后问题


package com.duoduo.day316;
/**
 * 一山不容二虎(n皇后问题)
 * 问题描述:  在n*n的棋盘上放置彼此不受攻击的n个皇后,按照规则,皇后可以攻击与之在同行同列同斜线的棋子。故如何放置?
 * 问题转化:  以行为主导(每行放置一个则不可能同行)--->在第n行放置第n个皇后,第n个皇后的位置不能与前n-1个皇后同列,同斜线
 * 算法设计:  1 定义问题的解空间:{x1,x2...xn} 分量xi表示第i个皇后放置在第i行第xi列 ,xi=1,2...n 
 * 			 2 解空间的组织结构:  一棵m(m=n)叉树   树的深度为n    (n*n)
 * 			 3 搜索解空间    约束条件--->在第t行放置第t个皇后时,第t个皇后的位置不能和前t-1个皇后同列,同斜线 
 * 						   即   xi!=xj不同列  |i-j|!=|xi-xj|  不同斜线
 *                                      限界条件---->不存在方案好坏的情况---->无需设置
 *           4 搜索过程  写代码
 *           
 * @author 多多
 *
 */
import java.util.Scanner;
import java.math.*;

public class Test5_5 {
	static int M=105;        				//定义默认数组大小
	static int n;            				//表示n个皇后
	static int [] x=new int[M];         	                //x[i]表示第i个皇后放置在第i行第x[i]列
	static int countn;                  	                //问题可行解的个数
	
	public static void main(String [] args) {
		Scanner sc=new Scanner(System.in);
		System.out.println("请输入皇后的个数n:");
		n=sc.nextInt();
		backTrack(1);    //从第一个节点开始搜索
		System.out.println("答案的个数为"+countn);
	}

	
	/*搜索过程*/ 
	private static void backTrack(int t) {    			                //t :搜索到第t层节点
		if(t>n) {                             			                //搜索到叶子节点  即存在可行解 则记录
			countn++;                        			        //可行解方案个数+1
			System.out.println("可行方案"+countn+"路径如下:");
			for(int i=1;i<=n;i++) { 		 			//打印选择的路径
				System.out.print(x[i]+" ");
			}
			System.out.println();
		}else {								       //约束条件   判断n个分支
			for(int i=1;i<=n;i++) {                 	               //循环给t赋值为n个位置
				x[t]=i;                       
				if(place(t))             		  	       //如果不冲突的话进行下一行的搜索
					backTrack(t+1);
			}
		}	
	}
	
	
    /*判断是否符合约束条件*/
	private static boolean place(int t) {            			        //判断第t个皇后能否放在第i位置上
		boolean ok=true;							
		for(int i=1;i


回溯法--n皇后问题_第1张图片

时间复杂度:

最坏情况下  最多有1+n+n2+n3...n*n-1次方)=n*n-1次方个节点需要扩展   每个节点要扩展n个分支  总分支数n*n次方

每个分支判断约束函数 O(n)     ------O(n*n+1次方)

叶子节点处输出可行解 O(n)-----做最坏情况(搜索到每一个叶子节点)----O(n*n+1次方)

总: O(n*n+1次方

空间复杂度:

x[] 作为 可行解记录路径的辅助数组  -----O(n)



算法优化:

上述求解方法中 ,解空间过于大

如何缩小解空间呢?

原方法:显约束:不同行    隐约束:不同列+不同斜线

显约束:可以控制解空间大小      隐约束:搜索解空间过程中判定可行解或最优解的

优化方法: 显约束:不同行+不同列    隐约束:不同斜线

结果:解空间明显缩小  -------->具体解法    请看下一帖    最优加工顺序问题

你可能感兴趣的:(左.算法,/,趣学算法)