近日准备蓝桥杯大赛,看到一个李白打酒的问题,题目如下:
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒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);
}
}
2126

被折叠的 条评论
为什么被折叠?



