问题描述
我创建了一个极小极大算法,该算法使用 alpha beta 修剪和转置表来加快搜索速度。我目前正在使用一个哈希图,它使用板状态作为键并将分数保存为值。 (游戏是 5x5 棋盘上的井字游戏)
这样做的问题是散列速度很慢,并且使用整个板状态作为密钥会占用大量内存。棋盘状态由具有 3 种可能类型的 2d 枚举数组表示:Blank、X 和 O。我想使用我自己的哈希(可能是 zobrist)作为键,根本不保存棋盘状态,但是哈希图会拿走我的钥匙并再次散列它。我曾考虑使用将键视为唯一的 btree 映射,但访问时间是 log(n) 而不是 O(1)。我也不关心键的顺序,所以 btree 似乎并不适合这里。
所以我的问题是,哪种数据结构在这里是理想的?即使它第二次散列我的密钥,我也应该使用散列图吗?
解决方法
我一直在做类似的事情,这是我最终得到的,适合您的情况:
-
紧凑板表示:假设有一个 5x5 板,每个单元格具有 3 个可能值之一:这意味着每个单元格可以使用 2 位,总计 25*2=50 位。这些将适合
u64
。这使得哈希映射中的哈希/存储条目非常便宜。就我而言,我还使用了
u64
(请参阅 https://github.com/phimuemue/brainball_solver/blob/master/src/main.rs#L20-L22),并考虑将这个值直接用作散列(指定一个自己的散列器,只是将值通过隧道),但是如果我回想一下,使用“真正的”哈希函数最终会更快。 (可能是更好的碰撞行为?) -
我最终手动内联了回溯的内容(参见 https://github.com/phimuemue/brainball_solver/blob/master/src/main.rs#L247-L253 和 https://github.com/phimuemue/brainball_solver/blob/master/src/main.rs#L267-L272),这大大加快了速度。
-
我使用生成的查找表 (https://github.com/phimuemue/brainball_solver/blob/master/src/main.rs#L17,https://github.com/phimuemue/brainball_solver/blob/master/build.rs#L37-L79) 来实现移动以加快移动速度。
所有这一切都是一粒盐。就我而言,它有助于加快搜索速度,但您必须单独测试您的案例。