如何表示汉诺塔的不同可能移动(状态)?

我正在尝试编写代码,使用UCS和A*算法解决汉诺塔问题,然后比较结果。因此,我首先要做的是将可能的移动表示为树,这样UCS和A*算法就可以轻松地遍历这棵树。

假设我们有3个堆栈和5个圆盘,那么初始状态将是:

# The Num of stacks is the number of elements in the list.# The Num of disks is the length of each element in the list.key = ["12345","00000","00000"]#         A       B        C

我需要构建一个函数来预测可能的下一步移动,因此下一步可能是:

["12340","00005","00000"] or ["12340","00000","00005"]# 所以这些状态将被保存为:dic ={}x= repr(key)dic[x] = ["12340","00005","00000"]# 结果:# ["12345","00000","00000"] : ["12340","00005","00000"]

我尝试了这个简单的代码:

# there are bugs but I am still working on it for indx, block in enumerate(key):    for i, char in enumerate(reversed(block)):        if char != "0":            for indx2, block2 in enumerate(key):                if indx2 == indx: pass                for ii, char2 in enumerate(reversed(block2)):                    if char2 == "0":                        temp=block[i]                        block[i]= block2[ii]                        block2[ii]=temp                        print(key)

有什么伪代码或想法可以帮助吗?


回答:

解决汉诺塔问题不需要构建状态图,因为有一个数学公式可以确定下一步的移动。

不过,如果你打算构建这个图,我建议将键简化为这种格式:12345||。管道符号分隔堆栈。所以如果你将5移动到中间堆栈,它的键将是1234|5|。然后如果你将4移动到最后一个堆栈:123|5|4,依此类推。

在创建图的过程中,你可以切换到列表的列表形式,如[["1","2","3"], [], []],这样更容易操作。你使用字典的想法很好,但是从一个状态可能有几个有效的移动,所以你需要一个状态列表。

图中的节点通常使用Node类实现,所以我建议使用以下代码:

class Node:    def __init__(self, key):        self.key = key        self.children = []def create_tree(stacks, tree=None):    if not tree:        tree = {}    key = "|".join(["".join(discs) for discs in stacks])    if key in tree:  # this node was already created        return tree[key]    tree[key] = node = Node(key)    for source in stacks:        if source:            disc = source[-1]            for target in stacks:                if not target or disc > target[-1]:                    # perform the move:                    target.append(source.pop())                    # recursion                    node.children.append(create_tree(stacks, tree))                    # undo the move                    source.append(target.pop())    return noderoot = create_tree([["1","2","3","4","5"], [], []])

运行此代码后,root将是一个Node实例,其children属性中有两个节点。这些子节点中的每一个将有三个子节点,包括一个指向根的反向引用,表示逆向移动。

我将字典(称为tree)隐藏在实现中。如果你觉得需要访问它,当然可以将其设为非局部变量,或作为参数传递。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注