您的位置:首页 > 其它

蓝桥杯——李白打酒,两种做法:递归与全排列

2018-03-22 01:11 281 查看
标题:李白打酒

话说大诗人李白,一生好饮。幸好他从不开车。

一天,他提着酒壶,从家里出来,酒壶中有酒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循环,累都累死了。当然,在没有别的办法下,能通过暴力法做出来是最好的了。

如发现有错误,欢迎指出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息