蓝桥杯 试题 算法训练 未名湖边的烦恼 python

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

分析
最开始我想复杂了,想用全排列去做,还鞋子是1,借是-1,这样的话就是生成所有的排列,然后算前缀和,小于0就break,但是m,n的范围比较大了,这么做就不太可行,很傻,有一个点过不去。后来寻思打个表,哈哈哈。

import copy
m,n=input().split()
m=int(m)
n=int(n)
num=0
def f(p,_str,n):
     global num
     if(_str[0]==-1):
          return
     if p==n:
          if(_str[0]==1):
               lpx=copy.deepcopy(_str)
               for i in range(1,len(_str)):
                    lpx[i]=lpx[i]+lpx[i-1]
                    if(lpx[i]<0):
                        break
                    if i==len(_str)-1:
                         num+=1
          return
     _str_part=sorted(_str[p:])
     _str[p:]=_str_part
     for i in range(p,n,1):
          if(i>p and _str[i]==_str[i-1]):
               continue
          _str[i],_str[p]=_str[p],_str[i]
          f(p+1,_str,n)
          _str[i],_str[p]=_str[p],_str[i]

aa=[1 for i in range(m)]
bb=[-1 for i in range(n)]
cc=aa+bb
f(0,cc,m+n)
print(num)




分析:
基于上面用1和-1表示的方法,还鞋用A表示,借鞋用B表示,可以抽象成m个A和n个B排列,要求是任意前i个必有A的个数不少于B,所以第一个一定是A,然后下一个数可能是A或B,如果是A的话,跟第一个数的情况相同,如果是B的话下一个只能选A(摘抄的别人的思路)
所以有了大家搜到的那个f(x,y)=f(x-1,y)+f(x,y-1)
用自然语言解释下就是f(x,y)表示剩下x个A,y个B(因为我们要排列A和B嘛),如果截止目前,还鞋子的比借鞋子的多,那么无所谓,下一个要么取A,要么取B。代码实现如下:

import copy
m,n=input().split()
m=int(m)
n=int(n)
def f(x,y):
     if(x==0 or y==0):
          return 1
     if(m-x==n-y):
          return f(x-1,y)
     if(m-x>n-y):
          return f(x-1,y)+f(x,y-1)
if m<n:
     print(0)
else:
     print(f(m,n))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值