任意一个像素,必须在三个方向上保证值唯一。这三个方向分别是X,Y,BOX。XY很好理解就是纵横的一条线(X,Y的像素个数就是N)。BOX指这个像素所在的BOX(BOX是由 (N的平方根)*(N的平方根) 个像素组成的矩阵)。
如图,一个9*9个像素的数独。(我把基数称为3)
1616的数独,16行,16列。同时分成44个BOX。(我把基数称为4)
那么如何生成一个有解的数独呢?
这个方法可行吗?
以下方法是按从左到右,从上到下的顺序来生成随机数的,看起来可行,实际上大多数情况下都无法生成有解数独,因为前面还比较容易满足条件,后面基本上就无法满足条件了。
以上方法最大的问题是,因为是左右,前后顺序在生成数独,实际上越到后面,会导致可以填充的满足XYB约束值越少,甚至没有。
而是每一步都选择在XYB方向上还有最大概率(即最多没有填充的值)的像素。(我不清楚下围棋先占4个角,是不是也是同样的道理?)
输入一个矩阵,得到另一个矩阵,表示当前位置在XYB轴的未填充值的个数。(非空值的xyb返回x,y,0,0,0)因为非空值不需要再填充它,所以无所谓。
1、首先要创建一个类型,包括数独矩阵的 X,Y坐标。以及这个坐标的横、竖、BOX三个方向上的剩余未填充值的个数。
ax int, -- 横坐标
ay int, -- 纵坐标
x int, -- 横向还有多少未填充像素
y int, -- 竖向还有多少未填充像素
b int -- BOX内还有多少未填充像素
);
2、编写一个函数,用来计算一个为完成数独矩阵,其每一个像素的XYB值。
3、用法举例
计算以下2为基数,4*4的矩阵的xyb值
{0,1,1,0}
{0,1,1,0}
使用unnest可以解开,按XYB三个方向总大小排序,再按某个方向最大排序,从而做到逐级收敛,真正每一次填充的像素,都是具备最大概率的像素。
postgres=# select * from
unnest(
comp_xyb('{ {1,2,3,4},{0,1,1,0},{0,1,1,0},{0,1,1,0} }', 2)
) t
where
t.x+t.y+t.b <> 0
order by
greatest(t.x,t.y,t.b) desc;
ax | ay | x | y | b
----+----+---+---+---
3 | 1 | 2 | 3 | 2
3 | 4 | 2 | 3 | 2
4 | 1 | 2 | 3 | 2
4 | 4 | 2 | 3 | 2
2 | 1 | 2 | 3 | 1
2 | 4 | 2 | 3 | 1
通过这个SQL得到了某个像素,这个像素的XYB方向上,还有最多的像素没有被填充。
用AX,ZY坐标值,往矩阵的这个像素填充符合数独条件的随机值,可以大幅提高构造可解数独的概率。
本文先介绍如何得到这样的一个像素,填充一个值进行,这个值的取值区间应该是最大的(最不会与数独的游戏规则违背),从而更大可能的生成一个完整可解的数独。
下面一篇文章再介绍如何生成一个N*N的数独。
http://poj.org/problem?id=3074
NP完全问题近似求解。