蓝桥杯 算法训练 未名湖边的烦恼Python(递归 简单动态规划两种方法)

问题描述
  每年冬天,北大未名湖上都是滑冰的好地方。北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩。
  每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个。现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)
输入格式
  两个整数,表示m和n
输出格式
  一个整数,表示队伍的排法的方案数。
样例输入
3 2
样例输出
5
数据规模和约定
  m,n∈[0,18]

分析:

假设还鞋的都叫A,借鞋子的都叫B,拿题目给的3个人还,2个人借来说,就是A,B的排列组合,手动(小白在线卑微。。。)排出来如下:

AAABB
AABBA
ABABA
ABAAB
AABAB

一共是这五种。我们知道还鞋的必须大于等于借鞋的,即m>=n,我们假设一个递归函数fun_Rec(m, n),返回的是m人还鞋,n人借鞋 的排列数。一个人,要么借鞋要么还鞋。

在这里插入图片描述
这个队伍从后面开始看,甲可能是借鞋子的,也可能是还鞋的,所以
fun_Rec(3, 2)就有两种可能:fun_Rec(3, 1),fun_Rec(2, 2)
所以递归关系来了:
fun_Rec(m, n)=fun_Rec(m, n-1)+fun_Rec(m-1, n)
在m>=n的时候递归
在m<n的时候返回0
在n=0的时候(就是没有人借鞋子的时候,只有一种排法)返回1

递归代码:

while True:
    try:
        def fun_Rec(m,n):   #m是还,n是借
            if n > m:
                return 0
            elif n == 0:
                return 1
            else:
                return fun_Rec(m, n-1) + fun_Rec(m-1, n)

        s = list(map(int, input().split()))
        m, n = s[0], s[1]
        print(fun_Rec(m, n))
    except:
        break

递归可以通过,我们简单想一下,流程可以这样看:
在这里插入图片描述
画红色框框的两个是一样的,我们递归的话,就要算两次,于是,我们可以把每次算过的存在一个地方,第二次遇到直接拿来用,于是,我们把代码改成动态规划:
动规的通式很简单:dp[x][y] = dp[x][y-1] + dp[x-1][y]
动规代码:

while True:
    try:
        s = list(map(int, input().split()))
        m, n = s[0], s[1]
        dp = [[0 for i in range(0, n+1)] for j in range(0, m+1)]
        for i in range(1, m+1):
            dp[i][0] = 1     #把没有人借鞋子的那一列都置为1,因为没人借鞋子的时候只有一种排法
        for x in range(1, m+1):
            for y in range(1, n+1):
                if x >= y:
                    dp[x][y] = dp[x][y-1] + dp[x-1][y]
                else:
                    continue
        print(dp[m][n])
    except:
        break

编程小白记录成长

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值