蓝桥杯 公园票价(递归)

公园票价为5角。假设每位游客只持有两种币值的货币:5角、1元。
再假设持有5角的有m人,持有1元的有n人。
由于特殊情况,开始的时候,售票员没有零钱可找。
我们想知道这m+n名游客以什么样的顺序购票则可以顺利完成购票过程。
显然,m < n的时候,无论如何都不能完成;
m>=n的时候,有些情况也不行。比如,第一个购票的乘客就持有1元。
请计算出这m+n名游客所有可能顺利完成购票的不同情况的组合数目。
注意:只关心5角和1元交替出现的次序的不同排列,持有同样币值的两名游客交换位置并不算做一种新的情况来计数。
回顾课程:《递归原理与构造技巧》

思路:下面给出两份代码,分别是从逆向推,和正向推。相比之下,逆向推要简单很多。

#include<iostream>
using namespace std;
//递减的递归 
int f(int m,int n){
    if(m<n)return 0;
    if(n==0)return 1;
    else return f(m-1,n)+f(m,n-1);
}

int main(){
    int m,n;
    cin>>m>>n;
    cout<<f(m,n)<<endl;
    return 0;
} 
#include<iostream>
using namespace std;
//递增的递归 

//m,n代表真实钱数,M,N代表目标钱数。 
int f(int m,int n,int M,int N){
    if(m<0||m>M||n>N) return 0;
    if(m==M&&n==N)return 1;
    return f(m+1,n,M,N)+f(m-1,n+1,M-1,N);
}
int main(){

    int m,n;
    cin>>m>>n;
    cout<<f(0,0,m,n)<<endl;
    return 0;
} 

其实递归写多了,你就知道里面的套路了,一般写递归就注意两个东西,一个是边界条件(也就是出口),另一个是方程。一般都是先写方程,再写出口。出口条件可以由方程中参数增减推出最极限情况,然后把这种情况排除,也就是return 0;
总结:参数设计-方程设计-边界条件设计。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个可能的解法: 首先,我们需要定义一个数据结构来记录每排凳子的状态,包括是否有人,是否有内向的人,是否有外向的人,以及座宽度等信息。可以使用一个二维数组来表示,第一维表示排数,第二维表示凳子置。例如,`seats[i][j]` 表示第 `i` 排第 `j` 个凳子的状态。 然后,我们按照顺序遍历每个上车的人,根据他们的类型和偏好选择合适的座。可以使用两个指针 `left` 和 `right` 来记录当前可用的一排凳子的左右边界,以及一个布尔变量 `found` 来记录是否已经找到符合要求的座。 对于外向的人,我们从左到右遍历每排凳子,找到第一个没人的一排,并记录下它的座宽度。如果后面还有符合要求的一排,就比较座宽度,选择最小的那排。然后将这排凳子标记为已有外向的人坐下,更新 `left` 和 `right` 的值。 对于内向的人,我们从左到右遍历每排凳子,找到第一个有人的一排,并记录下它的座宽度。如果后面还有符合要求的一排,就比较座宽度,选择最大的那排。然后将这排凳子标记为已有内向的人坐下,更新 `left` 和 `right` 的值。 最后,输出每个人所在的排数即可。 以下是 Python 代码实现: ```python n = int(input()) seats = [[{'occupied': False, 'inward': False, 'outward': False, 'width': int(input())}] * 2 for _ in range(n)] for i in range(n * 2): p = int(input()) # 0 for outward, 1 for inward if p == 0: found = False min_width = float('inf') for j in range(n): if not seats[j][0]['occupied'] and not seats[j][1]['occupied']: found = True if seats[j][0]['width'] < min_width: row, seat = j, 0 min_width = seats[j][0]['width'] if seats[j][1]['width'] < min_width: row, seat = j, 1 min_width = seats[j][1]['width'] if not found: continue else: found = False max_width = -1 for j in range(n): if seats[j][0]['occupied'] and seats[j][1]['occupied']: found = True if seats[j][0]['width'] > max_width: row, seat = j, 0 max_width = seats[j][0]['width'] if seats[j][1]['width'] > max_width: row, seat = j, 1 max_width = seats[j][1]['width'] if not found: continue seats[row][seat]['occupied'] = True if p == 0: seats[row][seat]['outward'] = True else: seats[row][seat]['inward'] = True print(row + 1) ``` 其中,输入格式为: ``` N W_1 W_2 ... W_N p_1 p_2 ... p_{2N} ``` 其中,`N` 表示排数,`W_i` 表示第 `i` 排的座宽度,`p_i` 表示第 `i` 个上车的人的类型和偏好(0 或 1)。输出格式为每个人所在的排数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值