李白打酒问题

近日准备蓝桥杯大赛,看到一个李白打酒的问题,题目如下:

话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:无事街上走,提壶去打酒。逢店加一倍,遇花喝一斗。这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb就是合理的次序。像这样的答案一共有多少呢???请你计算出所有可能方案的个数(包含题目给出的)。
注意:通过浏览器提交答案。答案是个整数。不要书写任何多余的内容。

这是一个问答题,只需提交答案即可,但是我想了想,我只能用程序穷举来得到答案,无奈上网搜了搜网友的解答。

解答一

链接

  • 既然是问答题,不要求代码,就直接推理出答案即可。
  • 李白有酒两斗,遇10次花喝10斗,说明五次遇店增加了8斗酒。
  • 五次加的酒的斗数可能分别为(1, 1, 2, 2, 2)或者(1, 2, 3, 1, 1)「不会再有其他情况,如果有一次加了4斗酒,必然有一次加可了两斗酒,五次加起来大于8,第二种情况是加了两斗酒之后遇花喝了一斗又遇店加三斗,所以(2, 3)是绑定在一起的」
  • 综上所述,所有可能的情况为C(5, 2) + C(4, 1) = 14

看到这个推理还是佩服的,能够将问题这样想。

解答二

链接

  • 将每个时刻剩余酒量,剩余的遇店次数,遇花次数和选择(遇店还是遇花)看作一个状态,遇店酒翻倍,遇花酒减一,直到还剩最后一次选择,遇最后一次花,喝最后一斗酒,博主将代码给出来,称为是深度优先遍历,感觉有这么点意思,但是递归不是更明显么?
    下面给出稍作调整后的代码
public class LiBaiDaJiu {
    // 计数,计所有情况的次数
    public static int counter;

    public static void dfs(int alco, int shop, int flower, int meet) {
        if (shop == 0 && flower == 1 && meet == 0 && alco == 1) {
            counter++;
            return;
        }
        // 遇店
        if (shop > 0) {
            dfs(alco * 2, shop - 1, flower, 1);
        }
        // 遇花
        if (alco > 0 && flower > 0) {
            dfs(alco - 1, shop, flower - 1, 0);
        }
        return;
    }

    public static void main(String[] args) {
        counter = 0;
        LiBaiDaJiu.dfs(2, 5, 10, -1);
        System.out.printf("%d\n", counter);
    }
}

解答三

链接

  • 解答和解答二思路基本类似,就是用递归的算法求解总次数,代码也比解答二写得更像递归,是我一开始就想的那种思路
public class Test011 {

    private static int counter;

    // jiu表示还剩多少斗酒,店表示还剩多少次店,hua表示还剩多少次花
    private static void libai(int step, int jiu, int dian, int hua) {

        if (step < 0 || jiu < 0 || dian < 0 || hua < 1) {
            return;
        }

        if (step == 0 && jiu == 1 && dian == 0 && hua == 1) {
            counter++;
            return;
        }

        libai(step - 1, jiu - 1, dian, hua - 1); // 遇到花了
        libai(step - 1, jiu * 2, dian - 1, hua); // 遇到店了

    }

    public static void main(String[] args) {
        counter = 0;
        libai(14, 2, 5, 10);
        System.out.println(counter);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值