`
evasiu
  • 浏览: 165212 次
  • 性别: Icon_minigender_2
  • 来自: 广州
博客专栏
Fa47b089-e026-399c-b770-017349f619d5
TCP/IP详解卷一>阅读...
浏览量:12240
社区版块
存档分类
最新评论

总共有多少个数独?

 
阅读更多
憋屈地看了一个星期的论文,实在是没一点意思。为了娱乐一下自己,兼受同学启发,我决定用python写一个数独游戏。从大二开始装了个ubuntu系统后,就发现了这个有趣的游戏。之后每次进入这个系统,非得先来几局数独;再到后来,为了玩数独,特意进了这个系统。喜欢这个自带的游戏的特点,界面简单,只做必要的错误提示,可以回溯,是我用过的最理想的数独游戏了,呵呵。至于我自己打算做一个数独游戏,纯粹是为了现学现用。自从开始学python以来,从来没有真正用它写过一段带有自己设计思想的代码,实是不该。何不就为自己做一个windows下也能玩的称心如意的数独呢?好了,取名就叫Eva's Sudoku~!不过话说回来,这篇文章的主题是:总共有多少个数独
这绝对不是一个简单的排列组合问题。关于这个问题,《编程之美》有过一个简单的推断介绍。根据里面找提供的一个网址,我找到了关于这个问题的详细解决方案[1]。现在让我们先做一些简单的规定:
1. 我们要求的是合法的数独总数,定为N
2. 对于数独中的9个块(block),分别命名如下:



3. 对于一个块(block),如果其内9个数字按如下方式排序,则称其为“标准型”:



总是可以通过替换使得一个块成为标准型的,这个过程叫做relabeling。这样的话,我们可以总是通过relabeling使B1成为标准型,对于一个B1是标准型的合法数独,它将可以通过relabeling得到9!个不一样的数独,因此,现在我们要求解的问题变成:
B1是标准型的合法数独有多少个?设该数为N1,我们有N=N1*9!。
好了,现在B1确定下来了,为了使数独合法,B2-B3总共有多少种可能呢?首先考虑B2的第一行,填写它的数字要么全部来自B1的第二行或第三行,要么是B1第二、三行的混合。B2-B3第一行的所有可能如下:



如果填写B2第一行的数字全部来自B1的第二行或第三行(我们称其为pure的情况),合法的B2-B3的填法如下(图为填写B2第一行的数字全部来字B1的第二行):



每行内部都可以全排,因此总共有(3!)^6种可能,再加上填写B2第一行的数字全部来自B1第三行的情况,对于pure的情况,总共有2*(3!)^6种可能。
如果填写B2第一行的数字是B1第二、第三行的混合(总共有18种组合方式),列取其中一种来看(其中a,b,c各代表1,2,3中的某个数),在这种情况下,包括全排列,总共会有3*(3!)^6种排列情况:



因此,B2-B3的合法可能共有:
M1=2*(3!)^6+18*3*(3!)^6=56*(3!)^6=2612736

为了让问题快速得到一个接近的解,我们使用探索法来进一步分析:
我们从九宫格的每一个块出发,如果每个块都由1~9填充,不再有其他限制,则合法的解共有N0=(9!)^9;进一步加上限制,块行中每一行都由1~9填充,其合法的解共有M2=9!*M1,九宫格里共有3个块行,因此使三个块行都合法的解共有M=M2^3,满足块行限制的解的个数在满足块限制解的个数中所占的比例为k=M/N0,同理满足块列限制的解的个数在满足块限制解的个数中所占的比例也为k。假设以上两个比例相互独立(事实上它们并不完全独立),则同时满足块行解和块列解在满足块限制解中的比较约为k^2,因此同时满足块行列限制的解(即九宫格的解)的总数约为N0*k^2~6.657*10^21。该估计结果与精确结果6.671*10^21相差大约0.2%。

现在让我们进入精确结果的求解过程:
总的来说,求解的思路是暴力求解。设置两个loop循环,外循环穷举所有在B1为标准型的情况下B2-B3所有可能的解,内循环则在B2-B3的解的情况下穷举所有合法的数独的解。

1. 外循环
现在我们知道了B2-B3所有可能的解的个数了(M1=2612736),外循环将执行200多万次!这一想就让人觉得遥遥无期,有什么办法能够减少穷举的次数呢?选代表~!我们总是能够通过行列变换、交换元素等方法来使一个数独转变成另外一个数独,这样的话,当我们知道了第一个数独的解法,我们自然而然就知道了第二个数独的解法,第二个数独将与第一个数独有同样的解法个数(不知道你明白我的意思了没?)由此我们可能在所有B2-B3可能的解(M1=2612736种)的集合中定义等价关系,从而使等价集中的待完成的数独具有相等个数的解。
怎么从一个数独转换成另一个数独呢?前面我们使用了relabeling技术,但事实上除了这个以外,还有其他技术,如块交换,例如我们交换B2跟B3,相应的解只需要交换B5跟B6,B8跟B9,完成B2-B3的解的个数将与完成B3-B2的解的个数相等。我们还可以对B1、B2、B3进行全排,下面的B4~B9只需做相应的顺序调整。虽然这将使B1不再是标准型的,但是别忘了我们还可以通过relabeling技术使它成为标准型的。甚至我们还可以对块的列、行进行全排。这些技术将帮助我们选举出一些特定的代表来进入内循环,内循环算出的该代表的个数乘以该代表所在集合的个数,将是该集合的合法的数独解的个数。我决定用数学公式来表达这些绕口的事情:



现在我们的目标就是减少这个外循环的次数k。上面的分析我们知道,对B2、B3内的列进行全排列得到的解属于一个集合,对B2、B3进行交换得到的解也属于一个集合。因此我们选取的代表具有如下特点:
1. B2,B3的第一行是增序的;
2. B2的第一行的第一个数字小于B3第一行的第一个数字。
每个代表都存在2*(3!)^2种原始序列通过转换(lexicographical reduction)变成该代表,也就是说,解决了一个代表的解的个数,我们实际上解决了72种情况下的解的个数,现在我们把外循环k由2612736降到了36288(=2612736/72)。
上面的做法事实上并没有完全地利用全排列与relabeling技术。对于这36288种可能,我们可以对B1-B2-B3进行全排列,也可以对每个块中的三个列进行全排列,从而可以得到6^4=1296种不同的解,然后对B1进行relabeling,再对B2-B3进行lexicographical reduction从而使其成为一个代表,这将使原先的36288个代表进一步降到只剩下2051个代表(具体得出的结果是通过程序完成的);更进一步,可以对B1-B2-B3的行进行全排列,然后再将B1进行relabeling变换得到一个新的可能,最终,可以得到416个代表。
有时候交换特定元素并不改变数独其他元素的解,例如下面块行,完成他们的解的个数的相同的(因此它们也是等价的):







除了列6跟列9的元素对(8,9)之外,列4、7的(1,2)、列1、4的(1,4)、列2、9的(5,8)以及列3、6的(6,9)之间的交换也能达到同样的效果。
更近一步,除了一对一的交换,还有2对2的交换等等,如下图:





通过消除这些等价关系,最终我们只剩下了71个代表。通过解答这71个代表,最终发现其实只有44种完全不同的代表。也就是说,最终我们可以将外循环降到k=44。

2. 内循环
内循环的工作就是针对B1-B2-B3的44种代表中的每一个,穷举所有合法的完整数独,然后根据我们上面提供的公式,即可求出N1进而求出N。但是我们精益求精,对B2-B3的进行选举代表的办法也同样可以运用到B4、B7上,当然,由于它受到更多的限制,我们只限制B4、B7的第一列是递增的,这样我们可以通过行的全排列来求出其他的数独,这样的做法使内循环的速度提升了72倍。

通过对这44种代表的穷举,我们最终将得到N1=18383222420692992,进一步得到N=N1*9!=6670903752021072936960 ~ 6.671*10^21。

------------------------
[1]http://www.afjarvis.staff.shef.ac.uk/sudoku/
  • 大小: 27.8 KB
  • 大小: 43.7 KB
  • 大小: 15.6 KB
  • 大小: 15.3 KB
  • 大小: 7.4 KB
  • 大小: 13 KB
  • 大小: 14.3 KB
  • 大小: 14.4 KB
  • 大小: 17.2 KB
  • 大小: 16.9 KB
  • 大小: 5.5 KB
0
0
分享到:
评论

相关推荐

    sudoku, 神经网络能破解数独?.zip

    数独是一个常见的数字谜题,要求你用数字填充一个X9网格,使每个列,每一行,每一行的数字都包含所有数字,从 1到 9. 有多种方法可以解决这些问题,包括计算方法。 在这个项目中,简单的卷积神经网络具有无规则后处

    数独代码 数独代码 数独代码

    数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码数独代码...

    数独验证器_sudoku验证器_数独验证_数独_

    数独验证器

    数独计算器 数独游戏 数独秒算

    数独计算器 数独游戏 数独秒算 本数独游戏 采用分为闯关模式和 随机模式,随机模式中的题库更多,闯关模式会随着 关数的增加而越来越难。...另外还有个数独计算器,妙算数独。 修复了上次数独计算器的2个BUG

    winform数独C#的数独游戏

    ​ 功能描述 winform数独C#的数独游戏 ...然后从完整无缺的数独结果中,随机取其中的若干(限定范围内的随机个数)个数字作为数独题目即可。取出的数字的数量越多,题目越容易,反之越难。   ​

    数独编辑器 可玩“杀手数独”喔

    小巧的数独编辑器,现在可以编辑标准数独、宫格数独、锯齿数独、超级数独(或者叫窗口数独)、杀手数独、时钟数独等,并且数独的尺寸不限定为3x3,比如宫格数独可以编辑3x2及3x4等等的地图尺寸。压缩包中附带了若干...

    100个数独(Python语言生成)

    100个原始的数独。可供杂志,报纸,网页引用。

    数独算法,数独游戏

    制作了一个简单的数独游戏,使用了非递归的算法数独结果。

    数独编辑器 源代码

    这个资源的源代码 原文: 小巧的数独编辑器,现在可以编辑标准数独、宫格数独、锯齿数独、超级数独(或者叫窗口数独)...本程序只是编辑器,鉴于网上有很多可以对数独进行求解的程序,本编辑器就先不添加求解功能了。

    用C语言生成一个随机数独.txt

    利用C语言生成一张可以玩的数独,但只是原始数据

    数独编辑器 1.002版

    小巧的数独编辑器,现在可以编辑标准数独、宫格数独、锯齿数独、超级数独(或者叫窗口数独)、杀手数独、时钟数独等,并且数独的尺寸不限定为3x3,比如宫格数独可以编辑3x2及3x4等等的地图尺寸。压缩包中附带了若干...

    微信小程序 小游戏类 数独小游戏 (源代码+截图)

    微信小程序 小游戏类 数独小游戏 (源代码+截图)微信小程序 小游戏类 数独小游戏 (源代码+截图)微信小程序 小游戏类 数独小游戏 (源代码+截图)微信小程序 小游戏类 数独小游戏 (源代码+截图)微信小程序 小...

    数独编辑器 1.001版

    小巧的数独编辑器,现在可以编辑标准数独、宫格数独、锯齿数独、超级数独(或者叫窗口数独)、杀手数独、时钟数独等,并且数独的尺寸不限定为3x3,比如宫格数独可以编辑3x2及3x4等等的地图尺寸。压缩包中附带了若干...

    数独游戏,随机生成只有唯一解的数独表

    用c#写了一个能够随机生成唯一解的数独游戏,很多其他人的都不是随机生成,而且也不能保证生成的数独表的解是唯一的,所以我自己写了一个可以随机生成唯一解的数独游戏,上传上来和大家一起学习学习,看看算法还有...

    VB-数独游戏源码元 发个数独游戏,用了自定义控件,界面淡入淡出

    vb数独游戏源代码 发个数独游戏,用了自定义控件,界面淡入淡出。 资源包源码列表: MSSCCPRJ.SCC FLayer.frm Button.ctl Button.ctx MSupport.bas FHowTo1.frm FHowTo1.frx FHowTo3.frm FHowTo3.frx FQuestion.frm ...

    高级数独辅助器.exe

    有图像化界面,有背景图案的那种,欢迎对数独热爱的人士下载,也欢迎对这个感兴趣的同行下载,我愿意无偿贡献出我的源代码,若对源码有需求的可以发电子邮件到3174991389@qq.com标题为:“求数独代码”我会以最快的...

    数独编辑器 黑色星期五版

    小巧的数独编辑器,现在可以编辑标准数独、宫格数独、锯齿数独、超级数独(或者叫窗口数独)、杀手数独、时钟数独、连体数独等,并且数独的尺寸不限定为3x3,比如宫格数独可以编辑3x2及3x4等等的地图尺寸。...

    数独数独数独 J2ME

    数独 J2ME 数独 J2ME 数独 J2ME 数独 J2ME

    MFC数独小游戏

    基于 MFC 编写的一个数独小游戏源码。支持简单、普通、困难三种难度;支持读档、存档;支持自动计算数独结果。 预置20个游戏文件,使用快速载入游戏可随机载入这些游戏,可使用创建新游戏来产生新的游戏及游戏文件...

    C语言做的模拟数独游戏系统

    用C语言做的模拟数独游戏做的代码,其中数独会随机生成

Global site tag (gtag.js) - Google Analytics