三壶谜题_Python

三个水壶的问题

有一个充满水的8品脱的水壶和两个空水壶(容积分别是5品脱和3品脱)。通过将水壶完全倒满水和将水壶的水完全倒空这两种方式,在其中的一个水壶中得到4品脱的水。

这道问题的思想就是对每一个状态进行扩展,并记录其前一个状态,然后放到list中记录(在记录过程中应判断这个状态之前是否已经被拓展过了),并以二叉树的数据结构的眼光看待这个list,为了更快地找到有4状态的节点,选择广度优先遍历的方式,借用队列的数据结构可以实现广度优先遍历。

定义节点的结构

class Node:
    def __init__(self, per=None, status=[8, 0, 0]):  # per 指向上一个节点,status表示当前状态
        self.per = per
        self.status = status
    def __str__(self):  # 调用print函数时会调用此接口,将其返回值打印
        return '{}'.format(self.status)

倒水的动作

def pour(cur_node, old_list, new_list):
    max_list = [8, 5, 3]  # 定义出每一个瓶子的最大容量
    r_list = cur_node.status # 先存储住当前状态
    # 认为是将瓶子 i 倒入到瓶子 j 中
    for i, j in ((0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 2)):
        n_list = r_list.copy()
        # 判断 i 是否有足够的的水将 j 倒满。如果有,倒满 j;如果没有,倒空 i
        # max_list[j] - r_list[j] 这个式子的结果为 j 还差多少水能够装满
        if r_list[i] > max_list[j] - r_list[j]:  # i 足够倒满 j
            n_list[j] = max_list[j]  # 将 j 倒满 
            n_list[i] = r_list[i] - (max_list[j] - r_list[j])
        else:  # i 不足够倒满 j,即倒空 i
            n_list[i] = 0
            n_list[j] = r_list[i] + r_list[j]
        # 这一步判断当前的 n_list 的状态是否已经被考虑过了
        flag = True
        for node in old_list:
            if node.status == n_list:
                flag = False
        # 如果未考虑过则将 n_list 添加到二叉树中
        if flag:
            new_node = Node(cur_node, n_list)
            new_list.append(new_node)

广度优先遍历

def print_ret(node):
    ret = []
    while node.per != None:
        ret.append(node.status)
        node = node.per
    ret.append(node)
    for i in range(len(ret) - 1, -1, -1):
        print('第{0}步:{1}'.format(len(ret) - i, ret[i]))
    
def BFS_node(root):
    old_list = []
    new_list = [root]
    while new_list != []:
        cur_node = new_list.pop(0)
        if 4 in cur_node.status:
            print_ret(cur_node)
            return
        old_list.append(cur_node)
        pour(old_list[len(old_list) - 1], old_list, new_list)
root = Node()
BFS_node(root)
第1步:[8, 0, 0]
第2步:[3, 5, 0]
第3步:[3, 2, 3]
第4步:[6, 2, 0]
第5步:[6, 0, 2]
第6步:[1, 5, 2]
第7步:[1, 4, 3]
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值