码题集 填矩阵

        有一个1xn的矩阵,现在往里面填方块,一共有三种方块:1×1的白块,1×1的黑块,1×k的黑块,方块放置时,必须是黑白交替的,矩阵不用填满,但要求最下面的块和最上面的块必须是黑色的,问有多少种放置方法。

码题集 填矩阵_第1张图片

码题集 填矩阵_第2张图片

         这道题我觉得大部分人的第一反应是采用递归的方法解决,我也是,代码如下:

# 设置函数用于递归,每次递归得到一种新的放置方法
def add_block(h):
    global n # 设置为全局变量
    global k
    global counts
    if h <= n: # 若高度小于等于h
        counts += 1 # 计数器加1
        add_block(h+1+1) # 继续递归,添加一个1x1白块和一个1x1黑块
        add_block(h+1+k) # 继续递归,添加一个1x1白块和一个1xk黑块

counts = 0 # 计数放置方法的总数
n, k = map(int, input().split()) # 输入数据

add_block(1) # 最底下为1x1黑块
add_block(k) # 最底下为1xk黑块

print(counts)

        看似没有问题,也确实代码是可以通过的,但是递归次数太多了,复杂度极高,很不推荐这种方法解决这道题。下面介绍利用排列的方法来做这道题,上代码。

# 阶层计算函数,同时也是全排列的计算函数
def factorial(n):
    if n<1:
        return 1
    res = 1
    for i in range(1, n+1):
        res *= i
    return res

n, k = map(int, input().split()) # 输入数据
sum = 0 # 计数放置方法的总数量
num1 = (n-1) // (1+1) # 除最低层外,最多放置1x1黑块的数量
num2 = (n-1) // (k+1) # 除最低层外,最多放置1xk黑块的数量
for i in range(num1+1):
    for j in range(num2+1):
        if 1+i*2+j*(1+k) <= n: # 当最底层可以是1x1黑块时,即高度小于等于n
            # 利用高中排列组合的知识,计算当1x1黑块为i个,1xk黑块为j个时,有多少种情况
            # 结果保存在临时变量count中
            count = factorial(i+j) // (factorial(i) * factorial(j))
            sum += count
        if k+i*2+j*(1+k) <= n: # 当最底层可以是1xk黑块时,即高度小于等于n
            sum += count

print(sum)

你可能感兴趣的:(码题集,oj赛题,python,算法,数据结构,组合模式)