今天看韩顺平老师讲解到递归最后一个例子,八皇后问题。但是老师没有评讲,直接留给大家去做了。虽然想偷懒,但还是坚持自己去攻克这道题了。花了一天的时间,始终找不到问题在哪儿。晚上通过群里一个朋友的帮助,总算搞清楚问题在哪儿了。我写的八皇后代码是这样的:

实在是输出不来,除了一个helloWorld什么也没有,也不知道到底哪里有问题

就网上搜了一下,找到一个帖子,写得蛮好的。代码是这样的

public class WolfQueen {/*** 一共有多少个皇后(此时设置为8皇后在8X8棋盘,可以修改此值来设置N皇后问题)*/int max = 8;/*** 该数组保存结果,第一个皇后摆在array[0]列,第二个摆在array[1]列*/int[] array = new int[max];public static void main(String[] args) {new WolfQueen().check(0);}/*** n代表当前是第几个皇后* @param n* 皇后n在array[n]列*/private void check(int n) {//终止条件是最后一行已经摆完,由于每摆一步都会校验是否有冲突,所以只要最后一行摆完,说明已经得到了一个正确解if (n == max) {print();return;}//从第一列开始放值,然后判断是否和本行本列本斜线有冲突,如果OK,就进入下一行的逻辑for (int i = 0; i < max; i++) {array[n] = i;if (judge(n)) {check(n + 1);}}}private boolean judge(int n) {for (int i = 0; i < n; i++) {if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {return false;}}return true;}private void print()  {for (int i = 0; i < array.length; i++) {System.out.print(array[i] + 1 + " ");}System.out.println();}
}

用这个代码运行一切正常,我对比了一下我的代码,除了没有把数组和数组长度作为成员变量之外,看上去没有任何区别。晚上在一位群友的帮助下,她建议我把判断皇后是否在同一条斜线上的条件写法改一下

for(int m = 0; m <= i-1; m++){if (arr[m] == j || Math.abs((i-m) / (j-arr[m])) == 1 )return false;
}

改成

for(int m = 0; m <= i-1; m++){if (arr[m] == j || Math.abs(i-m) == Math.abs(arr[i]-arr[m] )return false;
}

亦即将比值绝对值等于1改成绝对值相等。 改了之后果然!!!

但是我想了很久都还没想明白是怎么回事,到底是新手,思维转不过来,后来我分析,为什么用比值等于一会判断不出来呢,加上之前用下列语句测试输出过

//System.out.println("======i = "+i+"=======");for(int j = 0; j < 8; j++) {arr[i] = j;if (isOk(j, i, arr)) {if(i == 7) {System.out.println(Arrays.toString(arr)); // System.out.println("======i = "+ i +"==找到一次完整的===");return;} setColumn(i+1, arr);}
}
//System.out.println("======i = "+ i +"==找不到合适的列===");

这个结果代表回溯是没问题的,但是之所以没输出完整的数组,是i从来就没有等于过7。所以我在想,那肯定是条件限制了i无法等于7。也就意味着 【比值的绝对值等于1(斜率等于1)】这个条件比【绝对值相等】更严苛,把一些斜率不等于1的也给错误地判断为1了。所以,【比值的绝对值等于1】的条件判断下,其实扩大了范围,把一些不该返回false的情况也包含进去了。因为整除的话,比如4/3也会等于1,但其实这个时候两个皇后并不在一条斜线上,在isOk()这个函数里不应返回false,该给绿灯。用下面的语句去输出的时候

if ( Math.abs(i-m) / Math.abs(arr[i]-arr[m]) == 1){          System.out.println("i=" + i +" m=" + m + " j=" + j + " arr[m]=" + arr[m]);System.out.println("差值比值:" + Math.abs(  (i-m)  /  (j-arr[m])  )  );return false;
}

结果是下图这样的。

圈中的部分,就是被无辜开红灯的。因为比值根本不等于1,却因为整除而导致误判了。

花了一天的时间,最后找出了这样一个bug,真的很影响学习效率。但学习过程就是这样,要对自己有耐心。大概学习就是不断试错的过程吧。就像韩老师说的,我亦无他,惟手熟尔。加油啦

还有,看到网上的帖子分享的写法,是把赋值放在判断之前,

//从第一列开始放值,然后判断是否和本行本列本斜线有冲突,如果OK,就进入下一行的逻辑
for (int i = 0; i < max; i++) {array[n] = i;if (judge(n)) {check(n + 1);}
}

我的逻辑是相反的,先判断再赋值。

for(int j = 0; j < 8; j++) {if (isOk(j, i, arr)) {arr[i] = j;if(i == 7) {System.out.println(Arrays.toString(arr)); // System.out.println("======i = "+ i +"==找到一次完整的===");return;} setColumn(i+1, arr);}
}

这样也是OK的,没有问题。因为是在循环体内,无论先判断再赋值还是先赋值再判断,最后都是能经过判断的值被赋进去。

Java判断两个数“相等”和“比值为1”不等价相关推荐

  1. java 判断两个数是否异号

    java 整型int占4个字节32位,两个数异或后移动31位判断结果,如果是1则异号,如果是0则同号 1 public class ShowEnviromentViarible { 2 3 publi ...

  2. JAVA判断两个数是否亲和数_亲和数

    亲和数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  3. java判断两个数互质_AcWing 458. 比例简化-java(无需判断互质)

    因为数据范围很小,这道题的基本思路就是枚举所有的A'和B',找出最小的那个. 枚举需要满足下面两个条件 1.A'和B'互质 2.A'/B'的比例大于等于原来的比例,并且尽可能接近. 其实这里无需判断A ...

  4. Java判断一个数是不是快乐数

    Java判断一个数是不是快乐数 快乐数的定义: 快乐数(happy number)有以下的特性: 在给定的进位制下,该数字所有数位(digits)的平方和,得到的新数再次求所有数位的平方和,如此重复进 ...

  5. Java判断两个Date是不是同一天

    From: https://blog.csdn.net/xingchenbingbuyu/article/details/82734695 Java判断两个Date是不是同一天 1. 利用Calend ...

  6. [ Java ] 实现两个数加减乘除的简易计算器

    [ Java ] 实现两个数加减乘除的简易计算器 新手,不足之处望大佬们海涵 感谢( *ˊᵕˋ)✩︎‧₊ 以下为代码: package com.zhong.homework;import java.u ...

  7. C++: 判断两个数互质(最大公约数为1)

    **定理:gcd(a,b) = gcd(b,a mod b) ** // a和b的最大公因数,a和b的大小没影响. ①0和任意自然数的最大公约数就是那个自然数. ②互质指最大公约数等于1的两个自然数. ...

  8. JAVA判断一个数是否为质数

    JAVA判断一个数是否为质数 输入一个正整数N,判断该数是不是质数,如果是质数输出"N是一个质数",否则输出"N不是质数". 提示:质数的含义:除了1和它本身不 ...

  9. Java判断两个集合是否具有交集以及如何获得交集

    Java判断两个集合是否具有交集以及如何获得交集 一.Java判断两个集合是否具有交集 1.Collections.disjoint 2.CollectionUtils.containsAny 3.C ...

最新文章

  1. 解读 | 2019年10篇计算机视觉精选论文(上)
  2. 基于MAP-MRF的视差估计
  3. HTML标签大全(三)
  4. 从零开始编写自己的C#框架(9)——数据库设计与创建
  5. 软考-信息系统项目管理师-立项管理
  6. python水平_如何在python中水平透视表
  7. AutoHotkey调用VBA实现批量精确筛选数据透视表某字段内容。
  8. apache php的日志在哪里,PHP在哪里存储错误日志? (php5,apache,fastcgi,cpanel)...
  9. 进制转换练习-其它进制转换为十进制
  10. 开源!李飞飞团队给机器人打造一条龙训练!人类还能VR监管
  11. 提高Axure设计效率的10条建议 (转)
  12. 计算机主机一闪一闪的无法启动,电脑启动不了灯一闪一闪的
  13. 二分法之旋转有序数组
  14. android studio银联,android studio引入最新版银联支付功能
  15. Windows提示:您的许可证即将过期
  16. 连锁机构3D指纹考勤系统解决方案
  17. 壳聚糖/纳米金水凝胶/纳米木质素/掺杂二硫化钼/微米级Ag2O2掺杂壳聚糖水凝胶的制备研究
  18. JavaScript 数组方法every()
  19. BUUCTF——密码学——old-fashion
  20. 【密码学】Java课设-文件加密系统(适用于任何文件)

热门文章

  1. 论文阅读《Omnidirectional DSO: Direct Sparse Odometry with Fisheye Cameras》
  2. LED透明屏什么牌子好?2021年LED透明屏品牌排行榜
  3. Android 悬浮框按钮
  4. 疫情中饭店美食推荐软件开发的功能有哪些?
  5. 文献阅读(11):同步数据流SDF
  6. 神经科学探索脑第二十四章
  7. 肢体动作监测(WiFi通信)
  8. 一封搞搞笑的辞职信之流行歌曲篇
  9. PostgreSQL如何删除XLOG文件【补充】
  10. Seajs是什么及sea.js 由来,特点以及优势