平分酒水

  看似与图论完全无关的问题,也可以用图论解决。
  在一个容量为 v 1 v_1 v1的瓶中装满一瓶酒,还有两个容量分别为 v 2 v_2 v2 v 3 v_3 v3的空瓶,问将容量为 v 1 v_1 v1的瓶中的酒平分最少需要几次,以及如何倒水。当 v 1 v_1 v1为奇数时,平分向下取整。( b 1 > b 2 > b 1 2 > b 3 b_1>b_2>\frac{b_1}{2}>b_3 b1>b2>2b1>b3)

class BottleState(object):
    def __init__(self, bottle1, bottle2, bottle3, volumes):
        self.__bottles_state = [bottle1, bottle2, bottle3]
        self.__volumes = volumes

    def pour(self, from_bottle, to_bottle):
        if self.__bottles_state[from_bottle] < self.__volumes[to_bottle] - self.__bottles_state[to_bottle]:
            pour_volume = self.__bottles_state[from_bottle]
        else:
            pour_volume = self.__volumes[to_bottle] - self.__bottles_state[to_bottle]

        new_bottle_state = self.__bottles_state.copy()
        new_bottle_state[from_bottle] -= pour_volume
        new_bottle_state[to_bottle] += pour_volume
        return BottleState(new_bottle_state[0], new_bottle_state[1], new_bottle_state[2], self.__volumes)

    def get_state(self):
        return tuple(self.__bottles_state)

    def __eq__(self, other):
        return self.get_state() == other.get_state()


class BreadFirstPaths(object):
    def __init__(self, start, end):
        self.__start = start
        self.__end = end
        self.__marked = [start.get_state()]
        self.__former_state = [start]
        self.bfs()

    def bfs(self):
        fringe = [self.__start]
        while fringe:
            current_state = fringe.pop(0)
            if current_state == self.__end:
                break
            for from_bottle, to_bottle in zip([0, 0, 1, 1, 2, 2], [1, 2, 0, 2, 0, 1]):
                new_bottle_state = current_state.pour(from_bottle, to_bottle)
                if new_bottle_state.get_state() not in self.__marked:
                    self.__marked.append(new_bottle_state.get_state())
                    fringe.append(new_bottle_state)
                    self.__former_state.append(self.__marked.index(current_state.get_state()))

    def get_min(self):
        count = 0
        try:
            index = self.__marked.index(self.__end.get_state())
        except ValueError:
            return False
        while index != 0:
            count += 1
            index = self.__former_state[index]
        return count

    def get_path(self):
        path = []
        try:
            index = self.__marked.index(self.__end.get_state())
        except ValueError:
            return False
        while index != 0:
            path.insert(0, self.__marked[index])
            index = self.__former_state[index]

        path.insert(0, self.__start.get_state())
        return path


v1, v2, v3 = 10, 7, 3
volume = [v1, v2, v3]
end = v1 // 2
start_bottle_state = BottleState(v1, 0, 0, volume)
end_bottle_state = BottleState(end, end, v1 - 2 * end, volume)
bfp = BreadFirstPaths(start_bottle_state, end_bottle_state)
path = bfp.get_min()
if path is not False:
    print(path)
    print(bfp.get_path())
else:
    print('路径不存在')

  当然,此题还可以考虑使用裴蜀定理,将会大大降低时间复杂度与空间复杂度。在此不作讲述,有兴趣的朋友可以去力扣看一看。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值