2020字节跳动秋招笔试题——圆形花园的入口

小区花园里有n个入口,现在要修一些路,要求每个入口只能有一条路,且每条路之间互不相交,求输入为n的时候有几中修路的方式。n是一个输入为2-1000的偶数。

也就是偶数个圆上的点画不相交的直线有多少种画法。

2020字节跳动秋招笔试题——圆形花园的入口_第1张图片

首先要找到dp[ i ]和之前的dp之间的关系。换句话说怎么用之前的信息推出现在的修路条数。

2020字节跳动秋招笔试题——圆形花园的入口_第2张图片

以n = 8为例,之前的n = 6,4,2,0的情况都已经知道了。8是在6的基础上添加了两个点,例如把1,2连接在一起,剩下的就是6个点连接方式就是dp[ 6 ],1还可以连接哪些点呢?3是不可以的,因为要求直线不可以相交,1,3相连之后,2就被包围了,所以2的直线就肯定和别的直线相交。换句话说,从1开始和另外一个点把剩下的6个点分割成两个部分,这两部分只能内部连接,所以两部分的点数都必须是偶数。思路进一步等价=>遍历所有和等于6并且各自点数为偶数(包括0)的情况,又因为两个部分各自独立,所以总的情况等于两部分情况之积。所有的积之和就是当前的  dp[ 8 ]。推广到一般形式:8->n,6->n-2。

另外不用考虑不同的起点问题,以单一起点已经考虑了所有的情况,其他点作为起点的情况也被考虑在内了。

def catalanDP(n):
    dp = [0 for i in range(n+1)]
    # dp[0] = 0是为了dp[i-1]*dp[0]时候数值正常
    dp[0]=1
    dp[2]=1
    if n==0:
        return 0
    # 每次跳两个点,题目要求是偶数
    for i in range(4,n+1,2):
        # 拿出作为起点终点的两个点,之后剩下i-2个点
        # 每次跳两个点是为保证两部分内部直线不相交
        for j in range(0,i-2+1,2):
            dp[i] += dp[i-2-j]*dp[j]
    return dp[n]
print(catalanDP(6))

 

你可能感兴趣的:(笔试题)