目录
这蓝桥杯课难度比算法基础课低多了,我还是把蓝桥杯课看完了再看算法基础课。
1.递归和递推
递归实现指数型枚举
n = int(input())
st = [0] * (n + 1) # 0是不选, 1是选
def dfs(x):
if x > n:
for i in range(1, n + 1):
if st[i] == 1:
print(i, end = ' ') # 不选就不打,还是要换行
print()
return 0
st[x] = 0
dfs(x + 1)
st[x] = 1
dfs(x + 1)
dfs(1)
看下图,所有的递归都能写成递归搜索树的形式,可以很容易理解题目来写代码,建议刚开始画个树
写递归要先确定终止条件,但是递归还是很难想。。
递归实现排列型枚举
# acwing94. 递归实现排列型枚举 https://www.acwing.com/problem/content/96/
# 递归都很抽象,可以想像一个递归树,必要的时候可以画图
n = int(input())
st = [0] * (n + 1) # 数字是否被用过
# 这个不像上个题,必须要新开个数组保存序列
path = [0] * (n + 1) # 保存序列
def dfs(u):
if u > n:
for i in range(1, n + 1):
print(path[i], end=' ')
print()
return
# 这里不像上个题,有三个根节点,所以要这样
# 不用担心到3之后不会遍历2,1
for i in range(1, n + 1):
if not st[i]:
path[u] = i
# 回溯的时候要复原,很重要
st[i] = 1 # 数字被用,修改状态
dfs(u + 1) # 填下一个位
st[i] = 0 # 回溯,取出 i
dfs(1)
递归实现组合型枚举
# acwing 93. 递归实现组合型枚举 https://www.acwing.com/problem/content/95/
# 可以用来不重复
n, m = map(int, input().split())
path = [0] * (m + 1) # 保存路径
st = [0] * (n + 1) # 是否使用
def dfs(u):
if u > m:
for i in range(1, m + 1):
print(path[i], end=' ')
print()
return
for i in range(1, n + 1):
# 多了个升序,这个判断真是刚刚好,别的跟上个差不多
if not st[i] and i >= path[u-1]:
path[u] = i
st[i] = 1
dfs(u + 1)
st[i] = 0
dfs(1)
简单斐波拉契
# 717. 简单斐波那契从 https://www.acwing.com/problem/content/719/
# a总比fn慢2个位,因为a在最前面,a, b, fn
n = int(input())
fn = 0
a, b = 0, 1
while n:
print(a, end=' ')
fn = a + b
a = b
b = fn
n -= 1
费解的开关
这个代码还在打,有点难,现在看懂了正在打代码
2.二分与前缀和
基础课看过,先放
3.数学与简单DP
这后面三个题因为是数学问题,只要有公式就很简单。。。但是y总的题解还是可以看看的
买不到的数目
# acwing 1205. 买不到的数目 1205. 买不到的数目 https://www.acwing.com/problem/content/1207/
# https://www.acwing.com/solution/content/7101/
# 因为是数学知识。。
import math
n, m = map(int, input().split())
a = (n - 1) * (m - 1) - 1
print(a)
蚂蚁感冒
# acwing1211. 蚂蚁感冒 https://www.acwing.com/problem/content/1213/
# https://www.acwing.com/solution/content/7077/
# 上面的链接说得很清楚,我就不写了
n = int(input())
# 统计左边向右走的和右边向左走的
left, right = 0, 0
pivot = 0
for i in map(int, input().split()):
if not pivot:
pivot = i
else:
if abs(i) < abs(pivot) and i > 0: # 左边向右走
left += 1
elif abs(i) > abs(pivot) and i < 0: # 右边向左走
right += 1
if pivot < 0 and left == 0:
print(1)
elif pivot > 0 and right == 0:
print(1)
else:
print(left + right + 1)
饮料换购
# https://www.acwing.com/problem/content/1218/
# 还有刚开始要带的
n = int(input())
a = n
res = 0
while n // 3 >= 1:
res += n // 3
n = n // 3 + n % 3
print(res + a)
背包问题
摘花生
4.模拟枚举与排序
连号区间数
# acwing1210. 连号区间数 https://www.acwing.com/problem/content/1212/
# https://www.acwing.com/solution/content/6982/
# 重点是最大值-最小值 = 序列长度
# 然后就是遍历,开始我不知道怎么开始遍历,看视频说是取左端点和右端点
n = int(input())
m = list(map(int, input().split()))
minv, maxv = 1000000, 0
ans = 0
for i in range(n):
minv, maxv = 1000000, 0
for j in range(i, n):
minv = min(minv, m[j])
maxv = max(maxv, m[j])
if maxv - minv == j - i:
ans += 1
print(ans)
递增三元组
特别数的和
# 1245. 特别数的和 https://www.acwing.com/problem/content/description/1247/
n = int(input())
res = 0
# 如果tmp也设置成i,这与for里面的i是不冲突的
for i in range(n + 1):
tmp = i
while tmp:
t = tmp % 10
tmp //= 10
if t == 2 or t == 0 or t == 1 or t == 9:
res += i
break
print(res)
错误票据
# AcWing1204. 错误票据 https://www.acwing.com/problem/content/1206/
# 排序的特点
n = int(input())
nn, m = 0, 0
num = []
for _ in range(n):
for i in map(int, input().split()):
num.append(i)
num.sort()
for i in range(1, len(num)):
if num[i] == num[i - 1]:
m = num[i]
if num[i] - num[i - 1] == 2:
nn = num[i] - 1
print(nn, m)
回文日期
这个我用python中的time模块直接暴力枚举,超时了hhh有时间我去改下
5.树状数组与线段树
这个先放着,没时间看
6.双指针,bfs和图论
日志统计
献给阿尔吉侬的花束
这个是bfs的应用,感觉这种题差不多了,dfs差点,重点看格式
# acwing 1011 献给阿尔吉侬的花束 https://www.acwing.com/problem/content/description/1103/
# https://www.acwing.com/solution/content/9093/
# 这题虽然还好,但是debug了有一会儿,刚开始是没用函数写的,一直没找出来
# 还是用函数写简单些,以后尽量用函数写吧
from collections import deque
N = 200
t = int(input())
a = [[0] * N for _ in range(N)]
dxy = [(1, 0), (0, 1), (-1, 0), (0, -1)]
def dfs(start):
global r, c
q = deque()
bo = [[0] * N for _ in range(N)]
dis = [[0] * N for _ in range(N)]
q.append(start)
bo[start[0]][start[1]] = 1
while q:
tmp = q.popleft()
for i in dxy:
x, y = tmp[0] + i[0], tmp[1] + i[1]
if x >= 0 and y >= 0 and x < r and y < c and a[x][y] != '#' and bo[x][y] == 0:
q.append((x, y))
dis[x][y] = dis[tmp[0]][tmp[1]] + 1
bo[x][y] = 1
if (x, y) == end:
ans = dis[x][y]
return ans
return 0
for _ in range(t):
r, c = map(int, input().split())
for i in range(r):
j = 0
for tmp in input():
a[i][j] = tmp
if tmp == 'S':
start = (i, j)
if tmp == 'E':
end = (i, j)
j += 1
ans = dfs(start)
if ans != 0:
print(ans)
else:
print('oop!')
红与黑
和上面题类似就先不看了
交换瓶子
# AcWing 1224. 交换瓶子 https://www.acwing.com/problem/content/1226/
# https://www.acwing.com/solution/content/7917/
# 注意边界hhh
# 重要的是思想,把要交换的数看成一圈,然后最后要交换的次数就是圈数,可证
# 要记住的话就想不需要交换的话就是每个数都有自己的圈,圈数为树的个数
n = int(input())
a = [0] + list(map(int, input().split()))
cnt = 0
st = [0] * 10005
for i in range(1, n + 1):
if not st[i]:
cnt += 1
t = i
while not st[t]:
st[t] = 1
t = a[t]
print(n - cnt)
7.贪心
看了几题看来是要多做几次,先放下