2014蓝桥杯省赛——李白喝酒(递归、全排列、DFS)

本文探讨了李白饮酒问题的算法解决方法,通过DFS深度优先搜索和全排列两种策略,详细解析了如何计算李白在特定条件下饮酒次序的所有可能方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目描述】

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

 一天,他提着酒壶,从家里出来,酒壶中有酒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;
}

加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值