递归实现n(经典的8皇后问题)皇后的问题

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

问题描述:八皇后问题是一个以国际象棋为背景的问题:如何能够在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的时候有解

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航