java解决八皇后问题

八皇后问题:意思就是在8X8的棋盘上每一行,横或竖,甚至是对角线都不能有两个皇后同时出现

解决思路:

1,将八皇后问题转换成二进制问题来解决

2,用到递归的思想

先说说第一,转换为二进制问题,二进制中的1就表示皇后

大家可以看看以下二进制

00000001      十进制1   2的0次方

00000010      十进制2   2的1次方

00000100      十进制4   2的2次方

00001000      十进制8   2的3次方

00010000      十进制16   2的4次方

00100000      十进制32   2的5次方

01000000      十进制64   2的6次方

10000000      十进制128 (这里不考虑最高位是符号位)   2的7次方

大家看见没,如果用二进制的思想来解决八皇后的问题,那么,我们至少可以保证每一行(横或者竖)都只能有一个皇后出现

那么我们现在需要处理的就是需要从新排列一下,使其也不在一条斜线上。

我们只需要判断任意两个皇后不在对角线就可以了,我们可以很轻松的发现,相邻两个相除如果等于2的索引差次方,就是相邻的

如上面:16除以8等于2,相邻为1(5-4),2的1次方等于2;64除以8等于8,相邻为(7-4)3,2的3次方等于8

用代码来实现就是这样:


int m = buf[start]>=buf[i]?(buf[start]/buf[i]):(buf[i]/buf[start]);
if((int)Math.pow(2, i-start) == m){
        return false;
}
buf数组里存放的是十进制(1,2,4,8,16,32,64,128),大家可以先看看,后面给出全部的代码


看看下面的二进制排列方式

10000000    十进制128   2的7次方
00001000    十进制8      2的3次方
00000001    十进制1      2的0次方
00000100    十进制4      2的2次方
00100000    十进制32    2的5次方
00000010    十进制2      2的1次方
01000000    十进制64    2的6次方
00010000    十进制16    2的4次方

再说说第二,递归,递归主要是得到所有的全排列,因为你随便动一个数字就是一个新的排列


下面我给出全部的代码:


public class Demo {
	static int s=0;
	public static void main(String[] args) {
		int buf[] = {1,2,4,8,16,32,64,128};
		perm(buf,0,buf.length-1);
		System.out.println("s="+s);
	}
	
	//计算两两组合是否符合要求,既判断是否有两个皇后在一条斜线上,只要这个数组不符合,就返回false,执行下一个数组
	public static boolean zuhe(int[] buf,int start,int end){
		boolean b = true;
		while(start != end){
			for(int i = start+1;i<=end;i++){
				int m = buf[start]>=buf[i]?(buf[start]/buf[i]):(buf[i]/buf[start]);
				if((int)Math.pow(2, i-start) == m){
					return false;
				}
			}
			start++;
		}
		return b;
	}
	
	//将数组中的每一个数字转换为二进制输出,方便查看
	public static void Binary(int m){
		String s = Integer.toBinaryString(m);
		int L = 8 - s.length();
		while(L>0){
			s = "0" + s;
			L--;
		}
		System.out.println(s);
	}
	
	//递归,得到所有的排列
	public static void perm(int[] buf,int start,int end){
		if(start == end){
			if(zuhe(buf,0,end)){
				for(int i = 0;i<=end;i++){
					Binary(buf[i]);
				}
				System.out.println("~~~~~~");
				s++;
			}
		}else{
			for(int i = start;i<=end;i++){
//交换数据
				int temp = buf[start];
				buf[start] = buf[i];
				buf[i] = temp;
				perm(buf,start+1,end);
//还原数据
				temp = buf[start];
				buf[start] = buf[i];
				buf[i] = temp;
			}
			
		}
	}

}
以上代码还可以优化,我这里就不做解说了。



爆款云服务器s6 2核4G 低至0.46/天,具体规则查看活动详情Blog Img