李白喝酒问题

这篇博客探讨了一个关于李白在遇到店和花时饮酒的问题,通过递归算法寻找所有可能的解决方案。博主提供了两种递归代码实现,一种计算方案数量,另一种打印所有可能的次序。博客中详细解释了递归思路和剪枝策略,并提醒读者在面对类似问题时要仔细理解递归条件并尝试手动模拟递归过程来解决问题。
摘要由CSDN通过智能技术生成

题目
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
思路
在这里插入图片描述

可以看到,每次相遇,无论是遇到店子还是遇到花,它的下一次相遇还是花或者店
这个题一看就可以想到用递归,第一,它的每一步都可以分为两步,遇到店和遇到花。第二,递归条件清楚,最后一次遇到的是花,酒喝光,有15次相遇。
如果只要算有多少种方法,以下代码就可以:

#include<stdio.h>
//start表示开始的酒量
int main(){

 int f(int anum,int bnum,int start);

 int ans;

 ans=f(5,10,2);

 printf("%d",ans);

}

int f(int anum,int bnum,int start){

 if(anum==0&&bnum==0&&start==0)return 1;

 if(anum>=0&&bnum>=0&&start>0){

 return f(anum-1,bnum,start*2)+f(anum,bnum-1,start-1);

 }

 else return 0;

}

难的是如何把所有可能的情况都打印出来,这里我是看别人的代码看懂的

#include <stdio.h>

int cnt=0;

void dfs(char *a,int k,int alcohol,int drinkery)

{

     if (k==15)

     {

       if (alcohol==0 && drinkery==5 && a[14]=='b')

       {

           printf("%s\n",a);

           cnt++;

       }

       return;

     }

     if (drinkery<=5 && alcohol!=0)   // 剪枝

     {

           a[k]='a';

           dfs(a,k+1,2*alcohol,drinkery+1);

           a[k]='b';

           dfs(a,k+1,alcohol-1,drinkery);

       }

}

int main()

{

   char a[16];

   a[15]='\0';

   dfs(a,0,2,0);

   printf("Count=%d\n",cnt);

   return 0;

}


drinkery是用来记录当前遇到的店子的个数,也就是录入一个字符a,drinkery就加1,录入一个a,drinkery=1,录入两个a,drinkery=2…

遇到5个店子,所以剪枝的判断条件是drinkery<=5

k再这里有两个作用,一做字符录入的数组下标,二用来记录录入字符的总数,当录入a[14]='b’时,进入下一个递归,k=k+1,则已录入15个字符,进入递归出口判断。

这题我自己理解了很久,因为一个小错误,其它记录数据个数的变量和数组下标总比数组个数小1混为一谈了。真是发了个大神经。还有递归的题如果有困惑,不要怕麻烦,手写递归最开始的几步就可以很容易发现问题了。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值