蓝桥杯 算法训练 数字游戏 Python 90分

蓝桥杯 算法训练 数字游戏 Python 90分

“相邻两个数相加”得到下一个数,典型的杨辉三角。杨辉三角第4层为:contribute = [1, 3, 3, 1]

记输出weight = [3, 1, 2, 4],用线性代数的知识可得:contribute @ weight.T = 16

所以基本的思路就是:

1. 利用整数n求出杨辉三角第n层,记为contribute

2. 从字典序最小的序列开始枚举,验证输出是否满足条件

利用杨辉三角每个数都是组合数的性质,写出这个函数求contribute

def Pascal_triangle(num):
    """ 杨辉三角"""
    basic = 1
    cont = [basic]
    ele, is_even = divmod(num + 1, 2)
    # ele为不重复元素的边界
    for idx in range(1, ele):
        basic *= (num - idx) / idx
        cont.append(round(basic))
    if is_even:
        mirror = reversed(cont)
        # 偶数行: 无需回溯
    else:
        mirror = reversed(cont[:-1])
        # 奇数行: 需回溯
    cont.extend(mirror)
    return cont

num代表的是第n层

字典序初始化为:list(range(1, n + 1)),求下一个字典序的函数为:

def next_permutation(seq):
    """ 找到下个字典序
        exp: 8 3 7 6 5 4 2 1
               |       |    """
    n = len(seq)
    left = -1
    for idx in range(n - 2, -1, -1):
        if seq[idx] < seq[idx + 1]:
            # 找到顺序区的右边界
            left = idx
            break
    if left != -1:
        left_val = seq[left]
        for right in range(n - 1, left, -1):
            right_val = seq[right]
            if left_val < right_val:
                # 找到交换位
                seq[left] = right_val
                seq[right] = left_val
                seq[left + 1:] = reversed(seq[left + 1:])
                # 逆转逆序区
                return seq

以 [8, 3, 7, 6, 5, 4, 2, 1] 为例,这个函数完成的工作就是:

1. 从右到左开始查找,因为3 < 右边第一个数,所以记3的索引为left

2. 从右到左开始查找比3大的数,得到4的索引记为right

3. 交换left和right对应的数,此时序列变为 [8, 4, 7, 6, 5, 3, 2, 1]

4. 可以看到left右侧全是逆序的 (即4的右侧),所以逆转 seq[left + 1: ] 得到 [8, 4, 1, 2, 3, 5, 6, 7]

利用这个函数就可以枚举输出,每个输出记为weight。因为蓝桥杯是不支持numpy的,所以用这个函数验证:

def cal(order):
    return sum([m * n for m, n in zip(order, contribute)]) == summary

 90分还不错,结束

蓝桥杯 算法训练 数字游戏 Python 90分

上一篇:力扣--135:分发糖果


下一篇:LeetCode(Shell)- 194. 转置文件