清源绿里

用程序解决买啤酒问题

知乎上以及微信或者微博等地方出现买啤酒的问题,一般题目是这么描述的“哈尔滨啤酒搞促销,啤酒2块1瓶,4个盖换1瓶,2个空瓶换1瓶,10块可以喝几瓶?”。并不算太复杂,可以用纸笔画出来,或者甚至心算得到答案。但如果拿到的钱是100元、200元呢,恐怕没有那容易得到答案的。本着能用代码解决的事情绝不用画图解决的技术宅精神,编写了下列代码,可以用来解决买啤酒的问题。所有的输入都是作为变量,可以由用户自定义,以应对不同的问法。

使用钱、盖子和空瓶换啤酒的过程中,每一次交换的逻辑都是一样的,所以在本程序中使用了递归算法,也就是通过count_beer调用自己来完成每一步的计算。编写过程中遇到了递归函数中,return会返回所有原先进入压栈数据的问题,后来发现递归方法编写中return需要直接指向函数本身,否则执行结果将会是回到最初的输入数据。这也是递归的特性。

buy_beer_001

既然用程序的形式来解答问题,那么最大的好处就是所有的输入都可以是变量,可以用来分析题目本身。下图是如果你有100元,不同的盖子换购数目对应可以得到的啤酒总数,从结果中能够发现到了一定数目以后盖子换购对于最终数量是没有影响的。

Buy_beer_002

下图是在“4个盖子换1瓶、2个空瓶换1瓶”的条件下,不同的钱对应进行换购的次数,有意思的是即便钱数在变化,但该数据常常保持不变:

Buy_beer_003

下图是在“4个盖子换1瓶、2个空瓶换1瓶”的条件下,不同的钱能拿到的啤酒数目,可以理解,肯定是线性变化:

Buy_beer_004

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <iostream>

using namespace std;

//用钱、啤酒瓶盖子和空酒瓶来喝啤酒
//作者:Tsian
//时间:2015.12.05
//版本:1.0
//方式:每一次用钱、啤酒瓶盖子和空酒瓶换新啤酒的算法一致,故采用递归方式实现

int count_beer( int money, int price, int beer_lid, int empty_bottle, int beer_lid_exchange_rate, int empty_bottle_exchange_rate, int beer_counting, int round )
{
int new_bottle=0;//每一轮能换得的新啤酒瓶

//如果剩余的钱多于啤酒单价,则计算用钱能够买到的啤酒数目
new_bottle = money/price; //计算用钱能够买到的啤酒数目
money = money-new_bottle*price; //剩余的钱

//使用啤酒瓶盖子和空酒瓶换新啤酒
new_bottle = new_bottle + beer_lid/beer_lid_exchange_rate + empty_bottle/empty_bottle_exchange_rate;//用啤酒瓶盖子和空酒瓶换的新啤酒

beer_counting = beer_counting + new_bottle; //对于每一轮得到的新啤酒进行累计
beer_lid = beer_lid%beer_lid_exchange_rate + new_bottle; //计算本轮剩下的啤酒瓶盖子和新得到的啤酒瓶盖子总和
empty_bottle = empty_bottle%empty_bottle_exchange_rate + new_bottle; //计算本轮剩下的空酒瓶和新得到的空酒瓶总和
round = round+1; //计算第几轮购买或者换新啤酒

//输出每次购买或者换新啤酒的信息
cout<<"No."<<round<<" round:"<<" You can get "<<new_bottle<<" new bottles, "<<beer_lid<<" beer_lids, "<<empty_bottle<<" empty_bottles;"<<endl;

    if( money < price && beer_lid < beer_lid_exchange_rate && empty_bottle < empty_bottle_exchange_rate )
    {
        //如果钱、啤酒瓶盖子和空酒瓶都不能用来得到新的啤酒,则计算完成,返回得到的啤酒数目
        return beer_counting;
    }
    else
    {
        //如果钱、啤酒瓶盖子和空酒瓶还可以用来得到新的啤酒,则还在循环中,继续递归计算
        return count_beer( money, price, beer_lid, empty_bottle, beer_lid_exchange_rate, empty_bottle_exchange_rate, beer_counting, round  );
    }
}

int main()
{
    int price; //啤酒价格
    int beer_lid_exchange_rate; //几个盖子换一瓶
    int empty_bottle_exchange_rate; //几个空瓶换一瓶
    int money; //你有多少钱
    int total_beer; //能够得到的所有啤酒数目

    cout << "Please input beer price: ";
    cin >> price;

    cout << "Please input how many beer lid can change one new bottle: ";
    cin >> beer_lid_exchange_rate;

    cout << "Please input how many empty bottle can change one new bottle: ";
    cin >> empty_bottle_exchange_rate;

    cout << "How much do you have: " ;
    cin >> money;

    cout << endl;
    cout << "----------------------------------"<<endl;
    cout << endl;

    //调用递归函数,计算能够获得的啤酒瓶数目
    total_beer = count_beer( money, price, 0, 0, beer_lid_exchange_rate, empty_bottle_exchange_rate, 0, 0 );

    cout << endl;
    cout << "----------------------------------"<<endl;
    cout << endl;

    cout << "Totally you can get "<<total_beer<<" bottles!"  ;

    return 0;
}

文章评论

Leave a Comment