标题:李白打酒
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
注意:通过浏览器提交答案。答案是个整数。不要书写任何多余的内容。
主要介绍两种方法:简单递归,全排列
1.递归:
#include <iostream>
using namespace std;
int sum = 0;
void f(int a, int b, int c)
{
if(a > 0)
f(a-1, b, c*2);//不懂的,自己画画图就明白了,跟全排列差不多
if(b > 0)
f(a, b-1, c-1);
if(a==0 && b==0 && c==1) //c==1,由于最后一次是遇花,还未减去1,此时判断的结果刚好是李白喝完酒了
sum += 1;
}
int main()
{
f(5, 9, 2);//遇店a,遇花b,斗酒c(为何b=9?由于最后一次是遇花,不用考虑在内,否则要排除不是遇花的情况)
cout << sum << endl;
return 0;
}
2.全排列:
引入< algorithm>标准头文件,调用next_permutation(),最后排序后的数列是递减的。所以数组a中元素必须要递增写,否则不能罗列所有排列。
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[15]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,2,2,2,2};//-1遇花,2遇店
int n = 0;//记录总数
do{
int sum = 2; //初始斗酒数
for(int i=0; i<15; i++){
if(a[i] == -1){
sum += a[i];
}else{
sum *= a[i];
}
}
if(a[14]==-1&&sum==0){ //a[14]最后一次是遇花
n +=1;
}
}while(next_permutation(a,a+15));//全排列
cout<< n << endl;
return 0;
}
虽然说暴力法是万能的,但是有的时候,真的不好写,比如这道题,你起码要写15层for循环,累都累死了。当然,在没有别的办法下,能通过暴力法做出来是最好的了。
如发现有错误,欢迎指出。