【题目描述】
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
【问题分析】
题目的有效信息就是红色字体部分,题目可以简化为,李白从家里出来,有两斗酒,遇店5次,遇花9次,最后还剩一斗酒。拿到这个题目我的第一个想法就是递归求解。
【递归】f(w,store,flower):遇店store次,遇花flower次,酒剩w——我做失败了……噗,有空再贴出来
【DFS】
#include <iostream>
using namespace std;
int count=0;
void dfs(int store,int flower,int wine){
if(store>5)return;
if(flower>9)return ;
if(store==5&&flower==9&&wine==1){//满足条件,计数!
count++;
return;
}
dfs(store+1,flower,wine*2);
dfs(store,flower+1,wine-1);
}
int main(){
dfs(0,0,2);
cout<<"count="<<count<<endl;
}
【全排列】
【全排列1-----用c++自带函数求解】
我们利用STL中的next_permutation 函数,来排列出5次店,9次花的所有排列情况。如果你不知道这个函数具体是如何实现的,建议你先去了解一下,调用stl现有的库函数,会在竞赛过程中为我们节省很多的时间,高效而准确,你值得拥有!言归正传,简单的说,在代码中的do——while循环中,每一次都将数组a赋值为其中的一种排列情况!而我们需要做的就是判断这一种排列情况是否符合题目要求。于是乎,我们遍历这个存放遇见顺序的数组a,按题目所说,遇店我们就让酒翻倍,遇花就让酒减一。当我们按当前这种排列情况,遇见了5次店,9次花,再判断最后酒的情况。如果最后酒就剩一斗,那么就是满足条件的一种排列方式,计数器加1,并且输出这种排列。
#include <algorithm>
int sum=0;
using namespace std;
void f(char a[],int n){
do{
int w=2;//!!!!!非常重要!每一次初始情况都要保证,酒有两斗!
for(int i=0;i<n;i++){
if(a[i]=='a'){
w*=2;//遇店加一倍
}else if(a[i]=='b'){
w-=1;//遇花喝一斗
}
}
if(w==1){//遇到了五次店,九次花,还剩一斗酒
sum++;
for(int i=0;i<n;i++){
cout<<a[i]<<'\t';
}
cout<<'b'<<endl;
}
}while(next_permutation(a,a+n));
}
int main(){
char a[14]={'a','a','a','a','a','b','b','b','b','b','b','b','b','b'};
f(a,14);
cout<<"sum="<<sum<<endl;
}
加油!