程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 遞歸實現n(經典的8皇後問題)皇後的問題,遞歸皇後

遞歸實現n(經典的8皇後問題)皇後的問題,遞歸皇後

編輯: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。

  先定義全局變量:

? 1 2 3 private static int number = 0//表示答案數量     int count = 0;   //下文的數組下標     static String[] str ;  //保存正確答案的字符串數組,為了去除重復

   定義主函數:

? 1 2 3 4 5 6 7 8 9 10 11 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);     }

   下面執行遍歷操作的函數:

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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進行皇後位置判斷:

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 /*<br>     * 檢查兩個皇後是否在同一行,同一列,或者同一斜線上<br>     * 存在返回false<br>     * 不存在返回true<br>     */<br>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;     }

   刪除重復答案的函數:

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /*      * 將確定的解答數組,保存在一個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;     }

   下面進行對兩個皇後位置的判斷:

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /*      * 檢查兩個皇後是否在同一行,同一列,或者同一斜線上      * 存在返回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點的函數:

? 1 2 3 4 5 6 7 8 9 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+" ");             }         }     }

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

輸出案例:

? 1 2 3 4 請輸入皇後數字n:4 0,1 1,3 2,0 3,2 0,2 1,0 2,3 3,1 2

   n皇後問題在大於等於4的時候有解

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved