acwing蓝桥杯课python版代码

目录

1.递归和递推

递归实现指数型枚举

递归实现排列型枚举

递归实现组合型枚举

简单斐波拉契

费解的开关

2.二分与前缀和

3.数学与简单DP

买不到的数目

蚂蚁感冒

饮料换购

背包问题

摘花生

4.模拟枚举与排序

连号区间数

递增三元组

特别数的和

错误票据

回文日期

5.树状数组与线段树

6.双指针,bfs和图论

日志统计

献给阿尔吉侬的花束

红与黑

交换瓶子

7.贪心

8.数论

9.复杂dp


这蓝桥杯课难度比算法基础课低多了,我还是把蓝桥杯课看完了再看算法基础课。

1.递归和递推

递归实现指数型枚举

acwing 92. 递归实现指数型枚举

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.贪心

看了几题看来是要多做几次,先放下

8.数论

9.复杂dp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值