zoukankan      html  css  js  c++  java
  • 牛客网 多多的电子字典

    题目:多多鸡打算造一本自己的电子字典,里面的所有单词都只由a和b组成。
    每个单词的组成里a的数量不能超过N个且b的数量不能超过M个。
    多多鸡的幸运数字是K,它打算把所有满足条件的单词里的字典序第K小的单词找出来,作为字典的封面。

    输入描述:
    共一行,三个整数N, M, K。(0 < N, M < 50, 0 < K < 1,000,000,000,000,000)

    输出描述:
    共一行,为字典序第K小的单词。
    示例1
    输入
    2 1 4
    输出
    ab

    说明
    满足条件的单词里,按照字典序从小到大排列的结果是
    a
    aa
    aab
    ab
    aba
    b
    ba
    baa

    备注:
    对于40%的数据:0 < K < 100,000
    对于100%的数据:0 < K < 1,000,000,000,000,000
    题目保证第K小的单词一定存在

    题解:

    动态规划的状态是:dp[m][n]表示m个a n个b时候的单词数,dp[m][n] = dp[m][n - 1] + dp[m-1][n] + 2
    来源:牛客网

    我来解释一下为什么其他回答的递归为dp[m][n] = dp[m][n - 1] + dp[m-1][n] + 2
    假设m个a,n个b:
    那么假定第一个字母为a,这种的的个数为dp[m - 1][n] + 1 (额外加1是为了包括总长度为1,也就是只有这个a后面没有的情况, 即'a')
    那么假定第一个字母为b,这种的个数为dp[m][n - 1] + 1 (额外的1是为了包括总长度为1的情况,即'b')
    所以,dp[m][n] = dp[m][n - 1] + dp[m-1][n] + 2。

    比如dp[1][1] = dp[0][1] + dp[1][0] + 2 ,表示"一个a一个b" = "a开头,一个b" + "b开头,一个a" + 2
    dp[1][1]表示1个a一个b,这种的可能有a,ab,b,ba。
    dp[0][1]表示一个b,这种的可能有b。 (对应a开头,也就是ab)
    dp[1][0]表示1个a,这种的可能有a。 (对应b开头,也就是ba)
    显然还有a b没有算,这就是上面式子中的+2

    给出代码

    # @牛奶泡泡糖 https://www.nowcoder.com/profile/33750295
    def getcount(map,m,n):
        if not m:
            map[(m,n)]=n
        if not n:
            map[(m,n)]=m
        elif (m,n) in map:
            return map[(m,n)]
        else:
            #+'a'就是getcount(map,m-1,n)+1,加'b'同理
            map[(m,n)]=getcount(map,m-1,n)+getcount(map,m,n-1)+2
        return map[(m,n)]
    
    
    def mink(n,m,k):
        cur=""
        map= {}
        while k>0 :
            if n>0 and m==0:#只有'a'存在
                k-=1
                cur+="a"
                n-=1
            elif m>0 and n==0: #只有'b'存在
                cur+='b'
                k-=1
                m-=1
            elif n>0 and m>0 :#都存在时
                #计算a下所有子节点的和
                cnt=getcount(map,n-1,m) +1
                if cnt>=k:#在a子树下
                    cur+='a'
                    k-=1 #k相当于横向遍历,每次向右遍历一个节点
                    n-=1
                else:#在b子树下
                    cur+='b'
                    m-=1
                    k-=(cnt+1) #k要减去a子树的所有节点个数
        return cur
    
    
    from collections import defaultdict
    
    ss=list(map(int,input().split()))
    n=ss[0]
    m=ss[1]
    k=ss[2]
    p=mink(n,m,k) 
    print(p)
    












    种一棵树最好的时间是十年前,其次是现在。
  • 相关阅读:
    面试题39:二叉树的深度、判断二叉树是不是平衡
    Bridge 桥接
    Adapter 适配器
    search_request.go
    scoring_criteria.go
    index_init_oprions.go
    index.go
    engine_init_options.go
    document_index_data.go
    util.go
  • 原文地址:https://www.cnblogs.com/islch/p/13458439.html
Copyright © 2011-2022 走看看