zoukankan      html  css  js  c++  java
  • 【BZOJ2024】[SHOI2009] 舞会(动态规划)

    点此看题面

    • (n)个男人和(n)个女人,每个人有一个身高。
    • 先要将他们配成(n)对,满足最多有(k)对中女人比男人高,求方案数。
    • (nle200)

    动态规划+分类讨论

    我们先将所有男人和女人分别按身高排个序,然后设(f_{i,j})表示前(i)个男人和前(i)个女人配对产生(j)个女人比男人高的对的方案数。

    然后就是分类讨论。

    (i)个男人不矮于第(i)个女人

    首先考虑如果对数不变。

    一种情况是第(i)个女人替换了之前某个比配对男人高的配对女人,因为排过序,所以第(i)个女人肯定比这个配对男人高,而那个配对女人肯定不高于第(i)个男人。这一类方案数为(j)

    另一种情况是第(i)个女人替换了之前某个不矮于第(i)个女人的配对男人的配对女人。这与(j)无关,枚举(i)的时候可以直接统计,不妨设为(t)

    显然两种情况不可能重合(重合意味着存在一个比第(i)个女人高的配对男人,他的配对女人比他高,那就更比第(i)个女人高,但实际上我们是排过序了的),所以总方案数就是(j+t)

    而对数变化(1)的情况就是第(i)个女人总共(i)种配对方案减去对数不变的方案,即(i-j-t)

    综上,得到:

    [f_{i,j}=(j+t) imes f_{i-1,j}+(i-(j-1)-t) imes f_{i-1,j-1} ]

    (i)个男人矮于第(i)个女人

    其实也是类似的,同样先考虑对数不变。

    那么这个女人必须要替换之前某一对男女,满足配对男人矮于配对女人,且配对女人不高于当前男人。

    满足配对男人矮于配对女人的对数是(j),而我们考虑配对女人高于当前男人的必然更高于配对男人(假设这部分人数为(t)),也就是说这(t)种不满足条件的情况是被完全包含在这(j)种情况当中的,所以满足条件的方案数就应该是(j-t)

    对数变化(1)的情况仍旧是第(i)个女人总共(i)种配对方案减去对数不变的方案,即(i-j+t)

    综上,得到:

    [f_{i,j}=(j-t) imes f_{i-1,j}+(i-(j-1)+t) imes f_{i-1,j-1} ]

    Python

    由于这道题并没有给出模数,刚好最近在学习Python,所以偷懒了一些就直接用Python了。

    然而似乎因为对Python部分语法理解不够透彻,反而浪费了更长的时间。

    代码:(O(n^2))

    st=input().split()
    n=int(st[0])
    k=int(st[1])
    a=[0 for i in range(n+1)]
    for i in range(n):
        a[i]=int(input())
    b=[0 for i in range(n+1)]
    for i in range(n):
        b[i]=int(input())
    a.sort()#排序
    b.sort()#排序
    f=[[0 for i in range(n+5)] for j in range(n+5)]
    f[0][0]=1#初始状态
    for i in range(1,n+1):
        if(a[i]>=b[i]):#如果第i个男人不矮于第i个女人
            t=0
            for j in range(1,i+1):
                t+=(a[j]>=b[i])#统计之前不矮于比第i个女人的男人数量
            for j in range(0,i+1):
                f[i][j]+=(j+t)*f[i-1][j]#对数不变
            for j in range(1,i-t+1):
                f[i][j]+=(i-(j-1)-t)*f[i-1][j-1]#对数变化1
        else:#如果第i个男人矮于第i个女人
            t=0
            for j in range(1,i):
                t+=(b[j]>a[i])#统计之前高于第i个男人的女人数量
            for j in range(t,i+1):
                f[i][j]+=(j-t)*f[i-1][j]#对数不变
            for j in range(1,i+1):
                f[i][j]+=(i-(j-1)+t)*f[i-1][j-1]#对数变化1
    t=0
    for i in range(k+1):
        t+=f[n][i]#统计答案
    print(t)
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    idea的tomcat消失
    数据表南车
    ElementU日历Demo
    ElementUI表格行编辑单元格编辑支持(输入框,选择框)Demo
    expect ':' at 0, actual = (JSON转化异常解决)
    java获取日历格式的日期数据
    java判断某个日期在两个日期之间(区间) (包含或不包含两个日期)
    localDate和Date的转化
    ImmutableMap的put方法问题
    invalid comparison: java.time.LocalDate and java.lang.String
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ2024.html
Copyright © 2011-2022 走看看