zoukankan      html  css  js  c++  java
  • 校招真题练习033 音乐列表(贝壳)

    音乐列表

    题目描述
    小明喜欢在火车旅行的时候用手机听音乐,他有N首歌在手机里,在整个火车途中,他可以听P首歌,所以他想产生一个播放表产生P首歌曲,这个播放表的规则是:
    (1)每首歌都要至少被播放一次
    (2)在两首一样的歌中间,至少有M首其他的歌
    小明在想有多少种不同的播放表可以产生,那么给你N,M,P,你来算一下,输出结果取1000000007的余数

    输入描述:
    输入N,M,P
    N范围在1到100
    M范围在0到N
    P范围在N到100

    输出描述:
    输出结果mod 1000000007的余数

     1 import math
     2 n,m,p = map(int,input().split())
     3 dp = [[0 for _ in range(p+1)] for _ in range(n+1)]
     4 for i in range(m+1,n+1):
     5     for j in range(i,p+1):
     6         if j == i or i == m+1:
     7             dp[i][j] = math.factorial(i)
     8         else:
     9             dp[i][j] = dp[i-1][j-1] * i + dp[i][j-1] * (i-m)
    10 print(dp[n][p]%1000000007)

    算法思路:动态规划。

    本题目要计算的是,用n首不同的歌曲组成一个长度为p的歌曲列表,有多少种可能。

    其中有两个条件:

    1每首歌曲至少要播放一次,那必定p>=n,否则本条件无法满足,这个条件是隐含的,容易被忽略;

    2相同的两首歌中间,至少间隔m首其他的歌曲。

    举一个实际的例子来说明本题目的思路。假设n=4,m=2,p=5。

    定义dp[n+1][p+1]二维数组,初始值为0。每一个元素表示由i首歌组成长度为j的列表,有多少可能。显然dp[n][p]即为所求。

    i=0,表示有0首歌,其值都为0,表示不可能组成歌单。

    i=1,表示有1首歌,要分两种情况讨论:

      如果m=0,则值为1;如果m>=1,则值为0。本题m=2,因此值均为0。

    i=2,表示有2首歌,

      如果m=0,则2*2=4;如果m=1,则2*1=2;如果m>=2,则值为0。本题m=2,因此值为0。

    由以上分析可发现,从第0行到第m行的值均为0,那么只需要从第m+1行开始计算即可。见代码第4行:range(m+1,p+1)

    i=3,表示有3首歌,本题m=2,

      j=3,第一个位置有3种选择,第二个位置有2种选择,第二个位置有1种选择。见代码第7行math.factorial()计算阶乘。

      j=4,要计算的是3首歌生成一个长度为4的歌单,把此问题分成两部分考虑:

        第一部分,2首歌生成长度为3的歌单,间隔2首。左上 * i

        第二部分,3首歌生成长度为3的歌单,间隔2首。左 * (i - m)

      结果为两部分之和。

    但是为什么这样划分,我还没有想明白。只能先记录下来吧,也许以后能理解吧。

  • 相关阅读:
    资源汇总
    最近面试经历
    Screen Space Ambient Occlusion
    实时渲染下的多线程协作:实践
    High Dynamic Range
    Deferred Shading
    实时渲染下的多线程协作
    9.了解四个相等判断的用法
    14.使用构造函数链
    16.垃圾最小化
  • 原文地址:https://www.cnblogs.com/asenyang/p/11326834.html
Copyright © 2011-2022 走看看