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