Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 对15个谜题状态进行散列的有效方法的想法_Algorithm_Hash_Sliding Tile Puzzle - Fatal编程技术网

Algorithm 对15个谜题状态进行散列的有效方法的想法

Algorithm 对15个谜题状态进行散列的有效方法的想法,algorithm,hash,sliding-tile-puzzle,Algorithm,Hash,Sliding Tile Puzzle,我正在通过蚁群优化实现一个15个谜题求解器,我正在考虑一种有效地将每个状态散列成一个数字的方法,因此我浪费的字节数最少 状态由16个数字的列表表示,从0到15(0是孔) 比如: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0] 所以我想创建一个唯一的编号来标识该状态。 我可以把所有的数字转换成以16为基数的数字,但我认为这不是很有效 有什么想法吗 谢谢您的状态同构于16个元素的排列。一个45位的数字就足以枚举这些(log2 16!),但如果有益的话,我们还可以将其四

我正在通过蚁群优化实现一个15个谜题求解器,我正在考虑一种有效地将每个状态散列成一个数字的方法,因此我浪费的字节数最少

状态由16个数字的列表表示,从0到15(0是孔)

比如:

[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0]

所以我想创建一个唯一的编号来标识该状态。 我可以把所有的数字转换成以16为基数的数字,但我认为这不是很有效 有什么想法吗


谢谢

您的状态同构于16个元素的排列。一个45位的数字就足以枚举这些(log2 16!),但如果有益的话,我们还可以将其四舍五入到64位。问题归结为找到从状态到其在状态枚举中的位置的有效转换

知道0..16中的每个数字只出现一次,我们可以创建16个log2 16=4位的变量,其中第i个变量表示数字i出现的位置。这有相当多的冗余:需要log2(16)*16位,但正好是64位。它可以非常有效地实现(未经测试的伪代码):

state2number(状态):
idx=0
对于[0;16]中的i:
val=状态[i]

idx |=i有16!=2.09*10^13种可能的状态,需要大约44.25位进行编码

因此,如果要以字节为单位对状态进行编码,至少需要6个字节

为什么不这样编码:
让我们把这些值命名为a、b、c、d、e、f、g、h、i、j、k、l、m、n、o、p

值可以是

b`:= b - (b>a)?1:0;
c`:= c - (c>a)?1:0 - (c>b)?1:0
d`:= d - (d>a)?1:0 - (d>b)?1:0 - (d>c)?1:0
....
hashNumber=a+b
*15+c
*15*14+d`*15*14*15+

这将为您提供每个可能状态到一个适合6字节的数字的双射映射

如果需要,将数字转换回其引用状态也很容易


不是最优的,但快速是:
对于每个需要15*4位=60位的数字,使用4位(省略最后一位,因为它可以从前面的15个数字计算出来)。
可以存储在7.5字节中,或者如果你可以浪费更多,只需使用8字节即可。

谢谢!我想这应该是
对于0..15中的我来说
,但是是的,它工作起来很有魅力,再次感谢!@AlfonsoPérez我习惯于半开范围,但显然
是错误的符号,所以:Good catch.delnan,关于“高效”对不起,我没有具体说明,我只是想知道,在这个特殊的谜题中,“只有”16!/2个状态是可到达的,那么这样我们就“浪费”了几个字节,但我已经对它进行了另一种思考,我认为它真的没有必要那么迂腐。对不起,它不是更像:
idx |=val@alcoholisevil恭喜,你刚刚遇到了组合爆炸。有太多可能的游戏状态(16!/2~=10^13,正如OP在上面的评论中指出的)枚举它们或为它们中的每一个存储一些数据。我在回答中已经说过。仍然可以使用状态标识符执行一些有用的操作(例如,将其用作哈希映射或其他稀疏数组的键),但不可能有一个每个可能状态都有一个元素的完整数组
b`:= b - (b>a)?1:0;
c`:= c - (c>a)?1:0 - (c>b)?1:0
d`:= d - (d>a)?1:0 - (d>b)?1:0 - (d>c)?1:0
....