蓝桥杯 常用函数 Python

单源最短路

from math import inf


def Dijkstra(sourse, adj):
    ''' 单源最短路径 (不带负权)
        sourse: 源点
        adj: 图的邻接矩阵'''
    vex_num = len(adj)
    distance = [inf] * vex_num
    distance[sourse] = 0
    # 记录单源最短路
    undone = [True] * vex_num
    # 记录是否未完成
    while 1:
        min_idx = -1
        min_val = inf
        for idx, (dist, flag) in enumerate(zip(distance, undone)):
            if flag and dist < min_val:
                min_val = dist
                min_idx = idx
                # 找到 min_idx, min_dist
        if min_idx != -1:
            undone[min_idx] = False
            for idx, (dist, flag) in enumerate(zip(distance, undone)):
                if flag:
                    state = min_val + adj[min_idx][idx]
                    distance[idx] = min([state, distance[idx]])
        else:
            return distance


def SPFA(sourse, adj):
    ''' 单源最短路径 (带负权)
        sourse: 源点
        adj: 图的邻接矩阵'''
    vex_num = len(adj)
    distance = [inf] * vex_num
    distance[sourse] = 0
    # 记录单源最短路
    exist = [False] * vex_num
    exist[sourse] = True
    # 记录是否存在队列中
    count = [0] * vex_num
    count[sourse] = 1
    # 记录进入队列的次数
    queue = [sourse]
    # 初始化队列
    while queue:
        visit = queue.pop(0)
        cur_dist = distance[visit]
        exist[visit] = False
        # 队列: 弹出当前访问点
        for next_, weight in enumerate(adj[visit]):
            dist, flag, cnt = distance[next_], exist[next_], count[next_]
            new_dist = cur_dist + weight
            if new_dist < dist:
                dist = new_dist
                # 更新: 出边dist值
                if not flag:
                    flag = True
                    cnt += 1
                    queue.append(next_)
                    # 入队: 被更新点
                    if cnt > vex_num:
                        return False
                        # 终止: 存在负环
            distance[next_], exist[next_], count[next_] = dist, flag, cnt
    return distance

多源最短路

def Floyd(adj):
    ''' 多源最短路径 (带负权)
        adj: 图的邻接表'''
    vertex_num = len(adj)
    dist = adj.copy()
    for pass_p in range(vertex_num):
        for sourse in range(vertex_num):
            for end in range(vertex_num):
                attempt = dist[sourse][pass_p] + dist[pass_p][end]
                dist[sourse][end] = min([dist[sourse][end], attempt])

蓝桥杯【第11届决赛】补给 Python 20分https://hebitzj.blog.csdn.net/article/details/122792925

最小生成树

from math import inf


def Prim(sourse, adj):
    ''' 最小生成树
        sourse: 源点
        adj: 图的邻接表'''
    low_cost = adj[sourse].copy()
    last_vex = [sourse] * len(adj)
    # 记录 low_cost 中的边权对应的起点
    undone = [True] * len(adj)
    undone[sourse] = False
    # 记录顶点是否已作为出点
    edges = []
    while any(undone):
        next_ = low_cost.index(min(low_cost))
        begin = last_vex[next_]
        edges.append((begin, next_))
        # 找到权值最小边的端点
        low_cost[next_] = inf
        undone[next_] = False
        # 标记出点
        for idx, (old, new, flag) in enumerate(zip(low_cost, adj[next_], undone)):
            if flag and old > new:
                # 满足更优则更新
                low_cost[idx] = new
                last_vex[idx] = next_
    return edges

拓扑排序

from math import inf


def topo_sort(in_degree, adj):
    ''' AOV网拓扑排序 (最小字典序)
        in_degree: 入度表
        adj: 图的邻接矩阵'''
    seq = []
    while 1:
        visit = -1
        for idx, degree in enumerate(in_degree):
            if degree == 0:
                visit = idx
                in_degree[idx] = inf
                seq.append(visit)
                # 记录: 入度为0的顶点
                for out, weight in enumerate(adj[visit]):
                    if 0 < weight < inf:
                        in_degree[out] -= 1
                break
        if visit == -1:
            break
            # 搜索结束 / 存在环: 退出
    return seq

欧拉路径

def Euler_path(sourse, adj, search):
    ''' 欧拉路径 (遍历边各1次)
        sourse: 路径起点
        adj: 图的邻接表
        search: 出边搜索函数'''
    path = []
    stack = [sourse]
    while stack:
        visit = stack[-1]
        out = adj[visit]
        # 访问: 栈顶顶点
        if out:
            visit, out = search(visit, out)
            if out:
                stack.append(visit)
                # 入栈: 尚未满足途径点条件
            else:
                path.append(visit)
                # 入列: 满足途径点条件
        else:
            path.append(stack.pop(-1))
            # 入列: 满足途径点条件
    path.reverse()
    return path

下个字典序

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
    else:
        return None

蓝桥杯 算法训练 数字游戏 Python 90分https://blog.csdn.net/qq_55745968/article/details/122775005

杨辉三角

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 = cont[::-1]
        # 偶数行: 无需回溯
    else:
        mirror = cont[:-1:-1]
        # 奇数行: 需回溯
    cont.extend(mirror)
    return cont

蓝桥杯 算法训练 数字游戏 Python 90分https://blog.csdn.net/qq_55745968/article/details/122775005

合数判断

def is_comp(num):
    ''' 判断合数
        return: 最小因数'''
    if num <= 3:
        return False
    if not num & 1:
        # 是偶数
        return 2
    bound = int(num ** 0.5)
    # 搜索边界
    for mod in range(3, bound + 1, 2):
        if not num % mod:
            return mod
    return False

质数筛法

def prime_filter(num):
    ''' 质数筛选
        return: 筛选结果'''
    bound = int(num ** 0.5)
    result = [True] * (num + 1)
    # 初始化质数标志矩阵
    result[1] = False
    for mod in range(2, bound + 1):
        if result[mod]:
            # 找到质数,并作为最小因数
            for choose in range(mod ** 2, num + 1, mod):
                # 枚举合数: 最小因数的倍数
                result[choose] = False
    result.pop(0)
    return result

二分快速幂

def quick_power(basic, time, mod):
    ''' 二分快速幂
        mod: 求余数'''
    result = 1
    while time:
        if time & 1:
            result = result * basic % mod
        basic = basic ** 2 % mod
        time >>= 1
    return result

蓝桥杯 算法训练 数的潜能 Python 100分https://hebitzj.blog.csdn.net/article/details/122775159

最小公倍数

from math import gcd


def lcm(x, y):
    ''' 最小公倍数'''
    return x * y // gcd(x, y)

小根堆

import heapq


class Min_Heap(list):
    ''' 小根堆'''
    def __init__(self, seq=[]):
        super(Min_Heap, self).__init__(seq)
        heapq.heapify(self)

    def push(self, ele):
        # 元素入堆
        heapq.heappush(self, ele)

    def poproot(self):
        # 弹出堆顶元素并重排
        return heapq.heappop(self)

大根堆

import heapq


class Max_Heap(list):
    ''' 大根堆'''
    def __init__(self, seq=[]):
        super(Max_Heap, self).__init__(self._negative(seq))
        heapq.heapify(self)

    def push(self, ele):
        # 元素入堆
        heapq.heappush(self, - ele)

    def poproot(self):
        # 弹出堆顶元素并重排
        return - heapq.heappop(self)

    def _negative(self, seq):
        # 数值取反
        return map(lambda x: -x, seq)

    def value(self):
        return list(self._negative(self))

你可能感兴趣的:(蓝桥杯习题,算法,python,蓝桥杯)