动态规划之错排问题以及相应的变形

一.错排原理

何谓错排?错排就是完全乱序,比如有n个元素各有自己的编号,然后有各自相应的位置,位置号等于编号,所有元素的编号与位置号都不相等的情况叫作错排,那么求所有的情况数,则是一个动态规划问题。
当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用D(n)表示,那么D(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推.
第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法,只要元素号不放入对应的位置即可。
第二步,对于编号为k的元素,这时有两种情况:⑴把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法;⑵第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法;
综上得到: D(n) = (n-1) [D(n-2) + D(n-1)]; 特殊地,D(1) = 0, D(2) = 1.
接下来,进行关于错排题目以及一些变形的详解。

二.发邮件


由上可知,这是一个单纯的错排问题,D(n)表示所有情况。假设a的邮件A寄给了其他人,有n种情况,假设其中一种符合的情况,寄给了b,那么得看b的邮件B,如果寄给了a,那么这两人错排成功,那么剩下n-2个人重新按此进行推理,即D(n-2);如果没有寄给a,那么暂时只知道a错排成功,其它n-1个人得重新探索,即D(n-1)。所以D(n)=(n-1)(D(n-1)+D(n-2))。
代码实现:
#-*-coding:utf-8-*-
res=[0,0,1]
for i in range(3,21):
    res.append((i-1)*(res[i-1]+res[i-2]))
while True:
    try:
        n=int(raw_input())
        print res[n]
    except:
        break

三.年会抽奖


如上图所示,这就是一个错排变形的求概率的题。对于n个人错排的情况是D(n),而D(n)=(n-1)(D(n-1)+D(n-2)),而所有的抽奖情况则是n!;所以对于n个人,出现无人获奖的概率是:ans=D(n)/(n!)。
代码实现:
#-*-coding:utf-8-*-
res=[0,0,1]
ans=2
tmp=['0.00%','0.00%','50.00%']
for i in range(3,21):
    res.append((i-1)*(res[i-1]+res[i-2]))#求错排情况
    ans*=i#求所有抽奖的情况
    t=res[i]/float(ans)*100#求无人获奖的概率
    t='%.2f'%t
    tmp.append(str(t)+'%')
while True:
    try:
        n=int(raw_input())
        print tmp[n]
    except:
        break

四.考新郎



由上图所示,n个新娘之中有m个是选错的,则m个是错排问题,而n个中选m个是组合问题,其中n个选择m个情况是d=n!/((n-m)!m!),而m个错排问题则D(m)=(m-1)(D(m-1)+D(m-2));所以出现n个新娘之中有m个是选错的情况是ans=d*D(m)。
代码实现:
#-*-coding:utf-8-*-
res=[0,0,1]
for i in range(3,21):
    res.append((i-1)*(res[i-1]+res[i-2]))#错排情况
while True:
    try:
        n,m=map(int,raw_input().split())
        ans=1
        t=1
        #组合问题求n个中选m个新娘可能的情况。
        for i in range(n-m+1,n+1):
            ans*=i
        for i in range(1,m+1):
            t*=i
        ans=ans/t
        ans=ans*res[m]
        print ans
    except:
        break



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值