保存访问州信息的想法

Idea for keep information about visited states

本文关键字:信息 访问 保存      更新时间:2023-10-16

我现在制作了15个解谜器(在c++中(,但我的程序必须解决3x4谜题、8x8谜题等,而不是只有15个谜题。->X X Y谜题。我必须以某种方式保存访问状态的信息,我的第一个想法是制作树,例如:
谜题:

状态1
1 2
3 0

状态2
1 3
0 2

我把放在树上

root->1->2->3->0
 nbsp nbsp nbsp \_
 nbsp nbsp nbsp nbsp \->3->0->2

这也适用于益智游戏5x3、6x6等,适用于所有益智游戏

这个想法很有效,但它浪费了大量内存,而且添加节点需要一些时间:/所以效率非常低。

下一个想法是将访问的州保持在stl的std::map<>中,但是我不知道如何制作好的散列函数-从谜题状态中创建快捷方式(因为我不必存储谜题状态,我只需要访问过的信息。你有什么想法吗,对于std::map的密钥,或者其他保存状态访问过的信息的想法吗?

假设您只对解决谜题X*Y感兴趣,其中X,Y<=16.我会用一个X*Y字节的数组来表示谜题的状态,其中每个字节给出谜题中一个正方形的值。在一个奇怪的基数中使用字节而不是BigInteger可能会给你更快的访问和修改时间,因为比特运算往往很慢,在内存/速度权衡方面可能不是一个好的整体方法。

template<unsigned X, unsigned Y>
class PuzzleState {
    unsigned char state[X*Y];
    public:
    void set(unsigned x, unsigned y, unsigned char v) {
        state[x+X*y] = v;
    }
    unsigned get(unsigned x, unsigned y) {
        return state[x+X*y];
    }
    bool operator<(const PuzzleState<X, Y>& other) const {
        return memcmp(state, other.state, X*Y) < 0;
    }
};

然后只需将std::set<PuzzleState<8,8 >insertfind方法结合使用即可。在测试了性能是否仍然不合适之后,您可以使用一个简单的哈希函数(如Rolling hash(抛出一个哈希表,而不是std::set

我会将单个状态表示为BigInteger数(这里有一个c++实现,或者如果你想实现自己的,这里也有一个线程(。

假设你有一个(X,Y(维的拼图,你可以用基数=X*Y创建一个数字,这个数字的数字将代表被展平为一维的拼图。

例如:

State 1
1 2
3 0

这将被扁平化为

1 2 3 0

然后转换为基数为4的数字,如

state = (1 * (4^3)) + (2 * (4^2)) + (3 * 4) + 0;

这将唯一地识别任何谜题的任何给定状态。

Zobrist哈希在玩抽象游戏的程序中几乎无处不在。