zoukankan      html  css  js  c++  java
  • 递归实现n(经典的8皇后问题)皇后的问题

      问题描述:八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后, 使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上,此问题进而可以推广为n皇后的问题。

      解题思路:n*n的矩阵,递归每一个点,当皇后数量达到n的时候,进行判断,若满足题目条件,则答案加一(number++),否则继续进行遍历。

      保存皇后点的方法:构造一个二维数组reserve[][],当reserve[i][j] == 1时候,则该点已经有皇后,若reserve[i][j]==0则,皇后可以存在于该点,且该点置为一。

      判断皇后数量的方法,定义一个int sign ,当sign<8的时候递归遍历,并且重复上一操作,否则对reserve数组进行判断,判断此数组内等于1的点的坐标,是否满足题意,判断完之后,当前点置为0.

      判断x,y轴只需要判断是否有相等的坐标值即可。

      判断斜线,则判断每两个点之间坐标值相减的绝对值是否相等,(这里需要递归遍历每一个点)若相等,则点在斜线上重复,返回false,若不相等,则点在斜线上不重复,返回true。

      先定义全局变量:

    private static int number = 0;  //表示答案数量
    	int count = 0;   //下文的数组下标
    	static String[] str ;  //保存正确答案的字符串数组,为了去除重复
    

       定义主函数:

    public static void main(String[] args) {
    		com c = new com();
    		System.out.print("请输入皇后数字n:");
    		Scanner s = new Scanner(System.in);
    		int n = Integer.parseInt(s.nextLine());
    		int[][] reserve = new int[n][n]; //储存皇后的状态
    		str = new String[n*100];
    		int sign = 1;
    		c.startRun(reserve, n ,sign); 
    		System.out.println(number);
    	}
    

       下面执行遍历操作的函数:

    public void startRun(int[][] reserve , int n ,int sign){
    		for(int i = 0;i < n;i++){
    			for(int j = 0;j < n;j++){
    				if(reserve[i][j] == 0)
    					reserve[i][j] = 1;  //该点为一个皇后
    				else{
    					continue;
    				}
    				if(sign == n){
    					if(checkAllQuean(reserve,n)){  //对n皇后进行位置判断
    						output(reserve,n);  //一个输出函数,输出n皇后的点
    						System.out.println();
    						number++;
    					}
    				}else if(sign < n){
    						startRun(reserve , n ,sign + 1); //进行遍历操作
    					}
    				reserve[i][j] = 0;
    			}
    		}
    	}
    

       下面对数组reserve进行皇后位置判断:

    /*
         * 检查两个皇后是否在同一行,同一列,或者同一斜线上
         * 存在返回false
         * 不存在返回true
         */
    public boolean checkAllQuean(int[][] reserve , int n){ int[] x = new int[n]; int x1 = 0; int[] y = new int[n]; int y1 = 0; for(int i = 0;i < n;i++){ for(int j = 0;j < n;j++){ if(reserve[i][j] == 1){ x[x1++] = i; y[y1++] = j; } } }// 获得所有皇后的点坐标 for(x1 = 0;x1 < n;x1++){ for(y1 = 0;y1 < n;y1++){ if(x1 == y1) continue; if(!checkTwoQuean(x[x1],y[x1],x[y1],y[y1])){ //比较每一次n皇后的点点点点坐标 return false; } } } if(!checkReNumber(x,y,n)){ return false; } return true; }

       删除重复答案的函数:

    /*
    	 * 将确定的解答数组,保存在一个String[]里面,用来避免重复
    	 * 若重复则返回false
    	 * 不重复则返回true
    	 */
    	public boolean checkReNumber(int[] x,int [] y , int n){
    		String test = null ;
    		for(int j = 0; j < n;j++){
    			test += x[j]+""+y[j]+"";
    		}
    		for(String st : str){
    			if(st == null)
    				continue;
    			if(st.equals(test)){
    				return false;
    			}
    		}
    		str[count++] = test;
    		return true;
    	}
    

       下面进行对两个皇后位置的判断:

    /*
    	 * 检查两个皇后是否在同一行,同一列,或者同一斜线上
    	 * 存在返回false
    	 * 不存在返回true
    	 */
    	public boolean checkTwoQuean(int i , int j , int m ,int n){
    		if(i == m)
    			return false;
    		else if(j == n)
    			return false;
    		else if(Math.abs((m - i)) == Math.abs((n - j)))
    				return false;
    		else{
    			return true;
    		}
    	}
    

       下面是输出reserve点的函数:

    public void output(int[][] reserve , int n){
    		for(int k = 0; k < n;k++){
    			for(int h = 0;h< n;h++){
    				if(reserve[k][h] == 0)
    					continue;
    				System.out.print(k+","+h+" ");
    			}
    		}
    	}
    

       完,但是效率极低,非常低。

    输出案例:

    请输入皇后数字n:4
    0,1 1,3 2,0 3,2 
    0,2 1,0 2,3 3,1 
    2
    

       n皇后问题在大于等于4的时候有解

  • 相关阅读:
    第三方支付集成
    文件并发(日志处理)--队列--Redis+Log4Net
    ReportingServies——SQLServer报表开发综合实例
    C#开发可以可视化操作的windows服务
    4、ASP.NET MVC入门到精通——NHibernate构建一个ASP.NET MVC应用程序
    Lucene.net站内搜索—6、站内搜索第二版
    Lucene.net站内搜索—5、搜索引擎第一版实现
    Lucene.net站内搜索—4、搜索引擎第一版技术储备(简单介绍Log4Net、生产者消费者模式)
    谈谈爱情——祭奠那逝去的青春
    Lucene.net站内搜索—3、最简单搜索引擎代码
  • 原文地址:https://www.cnblogs.com/xiangxi/p/4921695.html
Copyright © 2011-2022 走看看