扇形涂色问题代码实现

在线编程测评–扇形涂色问题

近期在参加某公司的内推时,遇到了在线编程测试,考的就是扇形涂色问题的求解。题目的描述是这样的:

题目描述:将一个圆形划分为N个扇形,现有M中不同的颜色, 要求这N块相邻的区域不同色,问共有多少种不同的涂色方案(N>=1,M>=3)。
**举例说明:
当M=3,N=3时,输出的结果为6;M=5, N=5时,结果为1020。

题目分析

  • 当N=1时,说明对圆形不进行划分,那么此时用M种颜色进行涂色时,自然有M种方案。
  • 当N=2时,将圆形划分为两部分,此时用M种颜色进行涂色时,总共有 A2M A M 2 种方案。
  • N3 N ≥ 3 时,我们假设 S(n) S ( n ) 表示涂色到第n块扇形时的所有方案总数。可以这样分析:首先对第1块扇形进行涂色,共有M种涂色方案,即 S(1,M)=M S ( 1 , M ) = M ;对第2块进行涂色时,由于相邻的两块的颜色不同,所以第2块有M-1种涂法,即 S(2,M)=MM1 S ( 2 , M ) = M ∗ ( M − 1 ) ;以此类推,后面的每块都有M-1种。于是,总共的方案有 MM1N1 M ∗ ( M − 1 ) N − 1 种。但是这里面还包含了第1块和第N块涂色可能一样的情况,是不符合题意的,应该舍弃。对于这种情况(第1块和第N块涂色可能一样),可以等价于将第1块和第N块看成一块来涂色,那剩下的扇形,就有 S(N1) S ( N − 1 ) 种。这是一种递归的思想。因此,最后的总数
    S(N,M)=M(M1)N1S(N1,M). S ( N , M ) = M ∗ ( M − 1 ) N − 1 − S ( N − 1 , M ) .

代码实现

def fan_paint(m, n):
    if m < 3 or n < 1:
        return None
    # 首先考虑初始条件n=1或2的时候
    if n < 3:
        return combination(m, 2)

    # res = (m-1)**n + (-1)**n * (m-1)
    res = m*(m-1)**(n-1) - fan_paint(m, n-1)
    return res

# 用递归计算n的阶乘
def factorial(n):
    if n == 1:
        return 1
    return n * factorial(n-1)

# 计算排列组合,从n个里面选择m个进行排列组合
def combination(n, m):
    return factorial(n) / factorial(n-m)


if __name__ == '__main__':
    M = 5
    N = 5
    print(fan_paint(M, N))

上面的递推公式 S(N,M)=M(M1)N1S(N1,M) S ( N , M ) = M ∗ ( M − 1 ) N − 1 − S ( N − 1 , M ) ,如果将其进行求解,可以得到 S(N,M)=(M1)N+(1)N(M1) S ( N , M ) = ( M − 1 ) N + ( − 1 ) N ∗ ( M − 1 ) ,此时只有M,N,可以不用递归。

备注

如有问题或者别的求解方法,欢迎指教!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值