ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: yangyangzhifeng

[分享] 回溯法解数独,平均用时<0.2秒

[复制链接]

TA的精华主题

TA的得分主题

发表于 2013-10-22 21:12 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖已被收录到知识树中,索引项:其他结构和算法
不过遗憾的是,有时候这么做反而速度更慢……毕竟变化次数和剩余数最少并非绝对的正相关。

但大部分情况下可以得到好的表现。

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-10-23 07:50 | 显示全部楼层
像下面这个题,就退化太多了
未命名.png

TA的精华主题

TA的得分主题

发表于 2013-10-23 08:26 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
yangyangzhifeng 发表于 2013-10-23 07:50
像下面这个题,就退化太多了

不过,这样电脑随机生成的题目,随意性太大,本来就不适合用来做题目给人做。

→ 这样的题目,人脑无解。因为基本没有可以心算就可以确定的数字。

TA的精华主题

TA的得分主题

发表于 2013-10-23 08:52 | 显示全部楼层
其实,和直接按从左到右、从上到下顺序来计算的方法,本质上计算时的算法是一样的,
不同的只是对空白格子的试算时的顺序不同而已……


因此,直接按从左到右、从上到下顺序来计算时,也存在着需要大量耗费时间甚至死机的题目。


TA的精华主题

TA的得分主题

发表于 2013-10-23 08:55 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
我现在能想到的一个改进是:

不是按照剩余个数排序,而是按照每个空格的实际候选数的多少,从小到大来排序。

呵呵,这个应该是真正合理的方法,用空把代码写出来再比较一下。

TA的精华主题

TA的得分主题

发表于 2013-10-23 09:02 | 显示全部楼层
下面这个电脑随机题目,是按从左到右顺序测试时退化比较严重的→ 用你的代码大约 1.5秒

而顺序改进代码却只要 0.09秒

shudu4.jpg

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-10-23 09:58 | 显示全部楼层
香川群子 发表于 2013-10-23 08:55
我现在能想到的一个改进是:

不是按照剩余个数排序,而是按照每个空格的实际候选数的多少,从小到大来排 ...

我也尝试了,按实际候选数的多少排序写的代码,对有些题,退化比你写的那个还严重

TA的精华主题

TA的得分主题

发表于 2013-10-23 10:24 | 显示全部楼层
你们要是喜欢玩数独,建议你们自己写一段数独题的读写代码,方便交流
通行的办法是用一个81位长的字符串来表示一个数独题目,空格为0,先行后列,比如26楼的那个就可以表示为:
“000 000 007 470 650 120 000 070 006 500 700 000 104 900 000 007 000 600 340 017 209 902 300 780 700 000 003”
上面空格为了方便阅读,实际不需要。

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-10-23 11:35 | 显示全部楼层
按初始可选数排序代码如下:
  1. Sub sudoku2()
  2.     Dim ar, i&, j&, jg&(1 To 81), x&, t&, tt, jwz&(1 To 81), jcs(1 To 81), y&, xx&(1 To 9), k&, b&
  3.     Dim f_g&(1 To 9, 1 To 9), f_h&(1 To 9, 1 To 9), f_l&(1 To 9, 1 To 9)
  4.     Dim g&(1 To 81), h&(1 To 81), l&(1 To 81)
  5.     tt = Timer
  6.     ar = Sheet1.[b2].Resize(9, 9)
  7.     For i = 1 To 81
  8.         jcs(i) = xx
  9.     Next
  10.     For i = 1 To 9
  11.         For j = 1 To 9
  12.             x = x + 1
  13.             h(x) = i: l(x) = j
  14.             g(x) = ((i - 1) \ 3) * 3 + (j - 1) \ 3 + 1
  15.             jg(x) = ar(i, j)
  16.             If jg(x) > 0 Then
  17.                 If f_g(g(x), jg(x)) + f_h(h(x), jg(x)) + f_l(l(x), jg(x)) > 0 Then MsgBox "无解": Exit Sub
  18.                 f_g(g(x), jg(x)) = 1
  19.                 f_h(h(x), jg(x)) = 1
  20.                 f_l(l(x), jg(x)) = 1
  21.             Else
  22.                 y = y + 1
  23.                 jwz(y) = x
  24.                 For k = 1 To 9
  25.                     If ar(i, k) Then jcs(x)(ar(i, k)) = 1
  26.                     If ar(k, j) Then jcs(x)(ar(k, j)) = 1
  27.                 Next
  28.                 For b = ((i - 1) \ 3) * 3 + 1 To ((i - 1) \ 3) * 3 + 3
  29.                     For k = ((j - 1) \ 3) * 3 + 1 To ((j - 1) \ 3) * 3 + 3
  30.                         If ar(b, k) Then jcs(x)(ar(b, k)) = 1
  31.                     Next
  32.                 Next
  33.                 k = 0
  34.                 For b = 1 To 9
  35.                     k = k + jcs(x)(b)
  36.                 Next
  37.                 jcs(y) = k
  38.             End If
  39.         Next
  40.     Next
  41.     For i = 1 To y - 1
  42.         For j = y To i + 1 Step -1
  43.             If jcs(j) > jcs(j - 1) Then
  44.                 k = jcs(j): jcs(j) = jcs(j - 1): jcs(j - 1) = k
  45.                 k = jwz(j): jwz(j) = jwz(j - 1): jwz(j - 1) = k
  46.             End If
  47.         Next
  48.     Next
  49.     j = 1: t = 1
  50.     Do
  51.         If j > y Then Exit Do
  52.         x = jwz(j)
  53.         For i = jg(x) + 1 To 9
  54.             If f_g(g(x), i) = 0 Then
  55.                 If f_h(h(x), i) = 0 Then
  56.                     If f_l(l(x), i) = 0 Then
  57.                         jg(x) = i: t = 1
  58.                         f_g(g(x), jg(x)) = 1
  59.                         f_h(h(x), jg(x)) = 1
  60.                         f_l(l(x), jg(x)) = 1
  61.                         Exit For
  62.                     End If
  63.                 End If
  64.             End If
  65.         Next
  66.         If i > 9 Then
  67.             t = -1
  68.             jg(x) = 0
  69.             If j > 1 Then
  70.                 x = jwz(j - 1)
  71.                 f_g(g(x), jg(x)) = 0
  72.                 f_h(h(x), jg(x)) = 0
  73.                 f_l(l(x), jg(x)) = 0
  74.             Else
  75.                 MsgBox "无解": Exit Sub
  76.             End If
  77.         End If
  78.         j = j + t
  79.     Loop
  80.     For i = 1 To 81
  81.         ar(h(i), l(i)) = jg(i)
  82.     Next
  83.     Sheet1.[b12].Resize(9, 9) = ar
  84.     MsgBox Format(Timer - tt, "0.000s ")
  85.     Sheet1.[b12].Resize(9, 9).Interior.ColorIndex = -4142
  86.     Sheet1.[b2].Resize(9, 9).SpecialCells(xlCellTypeConstants, 1).Offset(10).Interior.Color = vbRed
  87. End Sub
复制代码
对下面这道题效果明显

*********
*21*4****
**4**6***
5**6*3***
*****8***
**9***2*1
8******6*
****2*4**
*******3*

TA的精华主题

TA的得分主题

发表于 2013-10-23 14:09 | 显示全部楼层
lee1892 发表于 2013-10-23 10:24
你们要是喜欢玩数独,建议你们自己写一段数独题的读写代码,方便交流
通行的办法是用一个81位长的字符串来 ...

呵呵,我们现在的代码中就是使用sj(1 to 81)来记录和处理数据的。


for  i=1 to 9
    for   j = 1 to 9

    next
next

方式效率高。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-5-6 17:00 , Processed in 0.036345 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表