算法学习笔记一 递归之八皇后分析

问题讲述

八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。

问题分析

现有一个8*8的网格 我们有8个皇后 需要将这8个皇后摆放到网格中使他们相互之间不能攻击彼此

我们首先想到的应该就是循环循环的确可以解除节,但是时间复杂度太高不可取

递归+回溯

我们可以利用递归来实现 因为我们 要做的事情其实就是一件事 判断当前位置可否放网格,那么我们就可以创建一个实现这个功能的函数然后反复调用。指导奖所有网格都判断结束
上述虽然能够找到解,但是找不到所有的解。所以我们就有用到了回溯,返回上一步或者上几步。那好直接上代码。用代码进行解释

package com.qiao.eq;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Place {
	int m = 0;
	int a[][] = new int[9][9];
	//创建一个数组存放皇后
	List<Object> list = new ArrayList<Object>();
	//创建一个list表单 添加记录
	public void getA(int a[][]) {
		this.a = a;
	}
	//获取数组


    //判断那个位置可以放置皇后,并记录
	public void putQueen(int n) {
		if(n<9) {
			for(int i=1;i<=8;i++) { 
			//判断该行的每个为值 如果 该位置可以摆放皇后 该位置值赋值为 1 跳转到下一行 知道这种方案结束 返回 该位置 将该值 重新赋值为0
			    //判断该位置能否放置皇后
				if(RowJudge(n,a)==1&&LineJudge(i,a)==1&&PrincipalDiagonal(n,i,a)==1&&FollowDiagonal(n,i,a)==1) {
					a[n][i] = 1;  // 满足条件 赋值为1 
					if(n==8) { 
					//如果 n == 8 及该皇后为最后一个皇后 有因为经过判断 该位置可以放皇后 所以 这是一种摆放方法
						m++;
						//m记录方案数量
						int b[][] = a;
						//创建一个新的数组 存储这种方案的摆放方式
						list.add(b);
						//将新的数组 存放到 list中 一种存储方式
					}
					putQueen(n+1);
					//继续调用 判断下一行 的八个位置能否摆放皇后
					a[n][i] = 0;
					//将 该位置的 值从新赋值为0 方便进行下一次判断 。
				}
			}
		}
	}
	
    //判断行是否已经有皇后
	public int RowJudge(int i,int a[][]) {
		int j;
		for(j=1;j<=8;j++) {
			if(a[i][j]==1) {
				return 0;
			}
		}
		return 1;
	}
    

    //判断列是否已经有皇后
	public int LineJudge(int i,int a[][]) {
		int j;
		for(j=1;j<=8;j++) {
			if(a[j][i]==1) {
				return 0;
			}
		}
		return 1;
	}
    

    //判断主对角线是否有皇后  左上及右下
	public int PrincipalDiagonal(int i,int j,int a[][]) {

		for(int m = j,n = i;n<=8;n++,m++) {
			if(m>8) {
				break;
			}
			if(a[n][m]==1) {
				return 0;
			}

		}
		
		for(int m = j,n = i;n>=1;n--,m--) {
			if(m<1) {
				break;
			}
			if(a[n][m]==1) {
				return 0;
			}
		}
		return 1;
	}

    //判断从对角线是否有皇后  左下及右上
	public int FollowDiagonal(int i,int j,int a[][]) {
		for(int m = j,n = i;n<=8;n++,m--) {
			if(m<1) {
				break;
			}
			if(a[n][m]==1) {
				return 0;
			}

		}
		for(int m = j,n = i;n>=1;n--,m++) {
			if(m>8) {
				break;
			}
			if(a[n][m]==1) {
				return 0;
			}

		}
		return 1;
	}
}

算法流程分析

首先 我初始化变量将数组所有值均赋值为0 然后 机型循环调用 为了找到所有方案 所以我采用行递归 即 每一次判断一整行
⑴ 判断该行每一个位置 如果当前位置满足条件往下执行⑵ 不满足 条件继续判断下一列
⑵ 将该位置的值赋值为1
⑶ 判断该行是否为第八行 及摆放的是否是最后一个皇后 如果是 从⑷执行 反之 从⑹开始执行
⑷ 方案数加一
⑸ 将该方案添加到list中
⑹ 继续判断下一行 如果行数大于9 该递归路径到此结束返回上一级
⑺ 将上一行的满足条件的那个值重新赋值为0 继续判断下一列 如果 满足条件从⑵开始执行
⑻ 如果 该行所有列均不满足条件 同样返回上一级 从⑺开始执行

反复执行改过程直到所有可能均找到。

你可能感兴趣的:(Java初学者,算法学习,算法分析)