|
我的PL/SQL代码已经更新到一楼主贴附件中。
addm的C++解法我看了,这个解法思路很简单, 因此代码比较好读。他对每个空位循环用1-9测试;测试的办法是和本行、列、区的所有非空值作比较。
我的方法则对此作了些预处理优化:我为每个空位建立了候选值清单,因为已知值是可以从里面划掉的,这样就不必1-9都测试;当检验一个值是否可用,我没有遍历和本行、列、区的所有位置,而是用了如下两种方法:
1.为每个行,列,区各设置9个标志位,某值被用过则置1, 回溯时重设为0. 这样有些额外动作,但只要三个判断就可决定某值是否可用,总体来说是合算的。
2.在我的版本3中放弃了标志位,采用维护候选值清单的办法。对每个空格设置一组指针,指向其后续的其它空格,当本空格取某值时,将它从后续空格的候选清单中删除。回溯时则补回去。用这个办法根本不用测试了,有值就是可用的;虽然它也多了维护清单的开销,额外的好处是在删除时如果发现已经是最后一个了,则可以快速放弃,相当于提早回溯。经过1000个题目测试,这方法比方法1更好。
addm对所有空格按照行,列的顺序处理,我事先排了一下序,当然这个排序没有理论支持,但实际效果不错。
addm先解好上下左右四个方位的所有解,最后穷尽所有解的排列来解中部的标准数独。我的方法则只有一条线,由于各空格的链接事先处理好,在对重叠部分求解的时候相当于一下子就解了两个题。
说了这么多,到底实际效果孰优孰劣?C++的用时0.07秒,PL/SQL用时0.35秒。毕竟PL/SQL是种解释型语言,和C++没得比。
如果addm老兄有空,把自己的C++代码移植到PL/SQL, 我很有兴趣再来PK一下! |
|