【预览】蓝桥杯竞赛python算法笔记 代码模板|吐血总结
文章目录
1 二分算法求分界值
想看到完整代码模板 请订阅专栏~
2 双指针算法
2.1 求最长的不包含重复数字的连续子序列
# 只会遍历整个数组一次
j=0
for i in range(n):
while(j<=i and check(j,i)):
j-=1
res=max(res,i-j-1)
3 排列组合
3.1 next_permutation 重排列一个序列 生成它的上一个序列
本代码的原题是luogu的火星人
# 对于12345的序列 最多让我数到54321
def nextP(index):
global s
for t in range(index):
if(n<=1): # 如果一共的字母小于等于1 没什么要干的 返回
return
for i in range(n-2,-1,-1):
# 从后往前看 找到第一个不是降序的数x
if(s[i]<s[i+1]):
for j in range(n-1,-1,-1):
if(s[j]>s[i]): # 从后往前找 找到第一个大于x的数
s[i],s[j]=s[j],s[i] # 把它们交换
s[i+1:]=sorted(s[i+1:]) # 后面按照升序排序
break
break
else:
if(i==0): s.sort()
n=int(input())
index=int(input())
s=[int(i) for i in input().split()]
nextP(index)
print(' '.join(map(str,s)))
# 没有括号的版本
def nextP(index):
global s
for t in range(index):
for i in range(n-2,-1,-1):
if s[i]<s[i+1]:
for j in range(n-1,-1,-1):
if s[j]>s[i]:
s[i],s[j]=s[j],s[i]
s[i+1:]=sorted(s[i+1:])
break
break
else:
if i==0:
s.sort()
n=int(input())
index=int(input())
s=[int(i) for i in input().split()]
if n>1:
nextP(index)
print(" ".join(map(str,s)))
3.3 n个数字/字母的不同排列
# n个数字的不同排列
from itertools import permutations
n=int(input())
s=[i for i in input().split()]
for p in permutations(s):
print("".join(map(str,p)))
# n个字母的不同排列
str=list(input().split()) # 根据空格划分开
for p in permutations(str):
print("".join(p))
3.4 n个数字选k个数的组合
想看到完整代码模板 请订阅专栏~
3.5 在n个数字中选1~n个数的不同组合
3.5.1 自己写dfs的方法
想看到完整代码模板 请订阅专栏~
4 组合数计算
组合数用这个公式来计算:
C a b = C a − 1 b + C a − 1 b − 1 C_a^b=C_{a-1}^b+C_{a-1}^{b-1} Cab=Ca−1b+Ca−1b−1 表示从a个苹果选择b个苹果 可以把选法(不重合不漏)分为2大类
- 包含此苹果 C a − 1 b − 1 C_{a-1}^{b-1} Ca−1b−1
- 不包含此苹果 C a − 1 b C_{a-1}^b Ca−1b
想看到完整代码模板 请订阅专栏~
5 快速幂
利用 a 2 0 , a 2 1 . . . a 2 l o g ( k ) a^{2^0},a^{2^1}...a^{2^{log(k)}} a20,a21...a2log(k)快速计算出幂(二进制的思想)
def qpow(a,k,mod):
res=1
while(k):
if(k&1): # 这里是取最后一位数
res=res*a%mod
k>>=1 # 右移一位
a=a*a%mod # 把乘积翻倍
return res
n=int(input())
for k in range(n):
a,k,p=map(int,input().split())
print(qpow(a,k,p))
6 求质数
6.1 试除法
6.2 朴素筛法
# 朴素筛法
N=1000010
n=int(input())
st=[0 for i in range(N)] # 记录是否是质数 0表示是质数
primes[0 for i in range(N)]
cnt=0
def get_primes(n): # 找出1-n的所有质数并存在primes[]数组中
global cnt,primes
for i in range(2,n+1):
if(st[i]==0): # i是质数
primes[cnt]=i
cnt+=1
for j in range(i+i,n+1,i):
st[j]=1
get_primes(n)
print(cnt)
6.3 线性筛质数-只用最小质因子来筛
想看到完整代码模板 请订阅专栏~
7 约数和约数有关
7.1 输出所有的约数
想看到完整代码模板 请订阅专栏~
7.2 约数的个数
想看到完整代码模板 请订阅专栏~
7.3 质因子分解
想看到完整代码模板 请订阅专栏~
8 欧几里得算法
8.1 欧几里得
# 简单的最大公约数
def gcd(a,b):
if b==0: return a
return gcd(b,a%b)
8.2 最小公倍数
最小公倍数=两整数的乘积/最大公约数
想看到完整代码模板 请订阅专栏~
9 图和树有关
9.1 建图方法
# 建立邻接表
N=100010
e=[0 for i in range(N)] # 存放的是各边的到达结点的号
ne=[0 for i in range(N)] # next指针数组 存放的邻接表的下一个节点的位置
h=[-1 for i in range(N)] # 头指针数组 指向这个结点的相邻结点(存放头结点在e中的index)
w=[0 for i in range(N)] # 边的权值
# dis数组存的是到达对应index结点的最短距离
idx=0
def add(a,b,c):
global idx,e,ne,h,w
e[idx]=b
w[idx]=c
ne[idx]=h[a]
h[a]=idx
idx+=1
# 访问某一个点的邻边的时候
t=h[a]
while(t!=-1):
node=e[t] # 一定要去e[t]才是真的点 不然只是一个下标
# 对这个node进行一波操作
t=ne[t]
9.2 最短路算法
9.2.1 单源最短路-dijkstra
dijkstra算法必须规定起点
(1)朴素dijkstra
不常用 背诵下面优化的dijkstra比较好
# 朴素 使用邻接矩阵存
N=510
g=[[float('inf') for i in range(N)] for j in range(N)]
st=[False for i in range(N)]
dist=[float('inf') for i in range(N)]
def dijkstra(start,end): # 从点start走到点end的路径
global dist,st,g
dist[start]=0
for i in range(n): # 遍历从start开始的n个点
t=-1
for j in range(1,n+1):
if(st[j]==False and (t==-1 or dist[t]>dist[j])): # t==-1 表示是遇到的第一个点 dist[t]>dist[j]表示要更新当前路径最短的点
t=j
if(t==end): # 最短路已经更新到了end
break # 如果要寻找到所有点的最短路不知道还要不要break
st[t]=True
想看到完整代码模板 请订阅专栏~
(2)堆优化dijkstra
想看到完整代码模板 请订阅专栏~
9.2.2 多源汇最短路-SPFA算法
SPFA是bellman-ford的改进版
SPFA算法可以算出从起点到任何点的最短路
想看到完整代码模板 请订阅专栏~
9.3 最小生成树算法
最小生成树算法在无向图上使用,背下来kruskal就可以了
9.3.1 kruskal最小生成树
想看到完整代码模板 请订阅专栏~
9.3.2 prim最小生成树
不常用 一般用kruskal
想看到完整代码模板 请订阅专栏~
9.3.3 拓扑排序
想看到完整代码模板 请订阅专栏~
10 差分算法
想看到完整代码模板 请订阅专栏~
11 并查集
# 并查集find函数
def find(x):
if(x!=p[x]): p[x]=find(p[x])
return p[x]
# 并查集union函数
for i in range(m):
a,b=map(int,input().split())
pa,pb=find(a),find(b)
if(pa!=pb): p[pa]=pb # 注意这里的操作!!
12 DFS和BFS
12.1 DFS
- 内部搜索(棋盘的结点作为结点)
- 外部搜索(棋盘的状态作为结点)
# dfs基本框架
def dfs():
12.2 BFS-和最短路有关的问题
# bfs基本框架
queue=[]
queue.append([sx,sy]) # 初始结点入队
while(queue):
front=queue.pop(0)
...
bfs最经典的是最短步数问题,每次向各个方向走一步的时候就step+1
13 DP背包模版(重点)
13.1 01背包
(1)二维/基本的01背包
想看到完整代码模板 请订阅专栏~
(2)一维的01背包
想看到完整代码模板 请订阅专栏~
13.2 完全背包
(1)朴素完全背包
想看到完整代码模板 请订阅专栏~
(2)优化的二维完全背包
想看到完整代码模板 请订阅专栏~
(3)优化的一维完全背包
想看到完整代码模板 请订阅专栏~
13.3 多重背包
(1)朴素的多重背包
想看到完整代码模板 请订阅专栏~
(2)二进制优化的多重背包
想看到完整代码模板 请订阅专栏~
13.4 分组背包-类似多重背包
想看到完整代码模板 请订阅专栏~
14 DP数字三角形
从下到上更新
n=int(input())
f=[]
for i in range(n):
f.append([int(i) for i in input().split()])
for i in range(n-2,-1,-1): # 从n-2(倒数第二行)到0行
for j in range(i+1): # 列内按从左到右 一列的数字个数是i+1个
f[i][j]+=max(f[i+1][j],f[i+1][j+1]) # 左下和右下较大
print(f[0][0])
从上到下更新
想看到完整代码模板 请订阅专栏~
15 DP的LCS模版
最长上升子序列
想看到完整代码模板 请订阅专栏~
最长公共子序列
想看到完整代码模板 请订阅专栏~
最长公共上升子序列
想看到完整代码模板 请订阅专栏~
16 记忆化搜索
摘花生
# 摘花生dp做法
T=int(input())
for t in range(T):
n,m=map(int,input().split())
f=[[] for j in range(110)]
f[0]=[0 for i in range(m+1)]
for i in range(1,n+1):
f[i]=[0]+[int(i) for i in input().split()]
for i in range(1,n+1):
for j in range(1,m+1):
f[i][j]+=max(f[i-1][j],f[i][j-1])
print(f[n][m])
# 摘花生记忆化搜索
def dfs(x,y):
global res,cur
dx=[1,0]
dy=[0,1]
cur+=f[x][y]
if(x==n and y==m):
res=max(res,cur)
return
for i in range(2):
xx=x+dx[i]
yy=y+dy[i]
if(xx<1 or yy<1 or xx>=n or yy>=m): continue
dfs(xx,yy)
cur-=f[x][y]
T=int(input())
res=0
cur=0
for t in range(T):
n,m=map(int,input().split())
f=[[] for j in range(110)]
f[0]=[0 for i in range(m+1)]
for i in range(1,n+1):
f[i]=[0]+[int(i) for i in input().split()]
dfs()
print(res)