思路导航

  • 前言
  • 一、一行代码
  • 二、迭代求解
  • 三、递归求解
  • 总结



前言

  空瓶换酒是一类很经典的智力趣题,也有很多不同的问题版本。本文旨在小结其解决方法,以加深理解。
  空瓶换酒的目标是求解最终能喝多少瓶酒?问题的版本有很多种:共有x元,y元一瓶酒,初始有x/y瓶酒,m个酒瓶可以换一瓶酒,n个瓶盖可以换一瓶酒。其还分为不可赊账和可赊账,此处讨论的是不可赊账版本,x/y取为num,m取2,n取4.(可赊账类转换为函数求解问题)


一、一行代码

此类思路的解法也有几种,最简单的思路便是总结规律,手动推导前几次便可发现其规律。

num

sum

bottle

lid

1

1

1

1

2

3

1

3

3

7

1

3

4

11

1

3

故可发现在num>1时:

sum = 4*num-5 if num>1 else 1

故可直接求解出相应答案,还可以利用动态规划的思想进行公式推导(最终结果同)。



二、迭代求解

代码如下(思路见注释):

# 空瓶换酒问题
""" wine:当前酒数量 bottle瓶子数 lid:瓶盖数 """
num = eval(input())
# 非递归思路
wine = num
bottle = 0
lid = 0
sum = 0
while True:
    if wine==0 and bottle//2==0 and lid//4==0:  #终止条件
        break
    elif wine!=0:     #消耗酒
        bottle+=wine
        lid+=wine
        sum+=wine
        wine=0
    elif bottle//2!=0:  #瓶子换酒
        bot_num = bottle//2
        wine+=bot_num
        bottle=bottle%2
    else:
        lid_num = lid//4   #瓶盖换酒
        wine += lid_num
        lid = lid%4
print(sum)

思路很简单,即迭代求解最终的喝酒数量,迭代的终止条件:当前可饮酒数为0且瓶子数和瓶盖数不支持换新酒。喝酒增加对应的瓶子数和瓶盖数,兑酒消耗对应瓶子数和瓶盖数。



三、递归求解

递归的思路相同,只不过换了种实现方式:

# 递归思路
num = int(input())
def for_wine(sum,wine,bottle,lid):
    if wine==0 and bottle//2 ==0 and lid//4 ==0:  #终止条件
        return sum
    elif wine!=0:   #消耗酒
        sum+=wine
        return for_wine(sum,0,bottle+wine,lid+wine)
    elif bottle //2!=0:  #瓶兑酒
        wine+=bottle//2
        return for_wine(sum,wine,bottle%2,lid)
    else:
        wine+=lid//4    #瓶盖兑酒
        return for_wine(sum,wine,bottle,lid%4)

print(for_wine(0,num,0,0))

总结

  以上就是本文的主要内容,本文简要地介绍了空瓶换酒问题,并引出了三种解决思路,并且以python语言模拟实现其求解过程,其他编程语言的实现类似。
  本文的实现可能还存在可以优化的地方,其主要目的是梳理相关解题思路,如有帮助,请点赞支持一下ヽ( ̄▽ ̄)ノ