【算法基础】空瓶换酒

文章目录

  • 空瓶换酒-python实现
    • 1.算法分析
      • 1.1 通常情况
      • 1.2 赊账情况

空瓶换酒-python实现

最近学习学习到一种空瓶换酒的算法,其题目描述为:假设一瓶啤酒2元钱,商家为了促销,规定:可以用2个空瓶子换一瓶啤酒,或者用4个盖子换一瓶啤酒。现在你身上有10元钱,可以买多少瓶啤酒。

1.算法分析

1.1 通常情况

首先假设最后可以用空瓶子换到 X X X个啤酒,可以用盖子换到 Y Y Y个啤酒,同时我们可以用N元钱一开始就买到M个啤酒,就可以得到下面的不等式:
X ≤ M + X + Y 2 < X + 1 X \leq \frac{M+X+Y}{2} < X+1 X2M+X+Y<X+1
Y ≤ M + X + Y 4 < Y + 1 Y \leq \frac{M+X+Y}{4} < Y+1 Y4M+X+Y<Y+1
上述两个公式说明,最后喝到的啤酒数量,肯定不能够再兑换多一个啤酒。

通过化简上述公式,可以得到以下公式:
M + Y − 2 < X ≤ M + Y     ( 1 ) M+Y-2 < X \leq M+Y~~~(1) M+Y2<XM+Y   (1)
M + X − 4 3 < Y ≤ M + X 3     ( 2 ) \frac{M+X-4}{3} < Y \leq \frac{M+X}{3}~~~(2) 3M+X4<Y3M+X   (2)
化简上述不等式之后,可以利用不断遍历循环,来验证不同值的情况。

举个例子:
当有10块钱,一开始可以买到 M = 5 M=5 M=5的啤酒数量,当 Y = 1 Y=1 Y=1时,通过公式(1)可以得到 X X X的取值范围为 X ∈ [ 4 , 6 ] X \in [4,6] X[4,6]。然后再把 X X X Y Y Y的几种情况代入到公式(2)进行验证。发现上述情况都不符合。

具体的python编程逻辑:

def cal_bar(moneny):
    x = 0
    y = 0
    m = moneny / 2
    for y in range(10):
        x_min = m + y -2
        x_max = m + y
        if x_max > x_min > 0:
            for i in range(x_min + 1, x_max + 1):
                if (m + i - 4) / 3 < y <= (m + i) / 3:
                    return i, y

    return None, None

结果可以喝到15瓶啤酒。

1.2 赊账情况

上面的情况是不能进行赊账的,如果能向老板进行赊账,则有有种原子操作:

  • 目前手上有1个瓶子,向老板借1个瓶子,然后兑换1个啤酒,喝掉啤酒后,还之前借的酒瓶,这时候的情况是:喝了1个啤酒,得到1个盖子
  • 目前手上有2个盖子,向老板借2个盖子,然后兑换1个啤酒,喝掉之后,这时候生产出1个空瓶和1个盖子,利用上面的操作再借空瓶,就可以再喝1个啤酒,这时候就可以还掉2个盖子,实际上:喝了2个啤酒,瓶子和盖子都没有剩下

使用这两种操作,可以得到比不能借的情况下更优的解:

def drink(moneny):
    total = 0
    wine, bottle, lid = moneny / 2, 0, 0
    while True:
        if wine != 0:
            total += wine
            bottle += wine
            lid += wine
            wine = 0
        elif bottle != 0:
            total += bottle
            lid += bottle
            bottle = 0
        elif lid >= 2:
            total += (lid / 2) * 2
            lid %= 2
        else:
            break
    return total

最后可以得到喝了20瓶啤酒。

你可能感兴趣的:(算法)