八皇后问题:意思就是在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/天,具体规则查看活动详情