蓝桥杯Python b组 个人复习笔记(week4)

本文作者分享了搜索算法(包括DFS和BFS)的学习心得,涉及并查集的真题练习,以及在蓝桥杯竞赛中的应用实例。通过解决实际问题,强调了由易到难的学习方法和解决问题的重要性。
摘要由CSDN通过智能技术生成

个人总结:

本周在调整状态后,一举拿下搜索算法的知识点.个人感觉算是入门了,可堪一看.供大家参看.除了搜索算法之外,也刷到了几道并查集和几道思维题,碍于篇幅只展现部分题目,大家有所收获后可以自行多加练习.

并查集:

那么接下来先来两道并查集真题热热身:(以下两道题的题目直接找训练系统一搜即可,后续不附题目的同理)

合根植物:

# 需要输出根数
def root(x):
    if p[x] != x:
        p[x] = root(p[x])
    return p[x]

def union(x, y):
    if root(x) != root(y):
        p[root(x)] = root(y)

m,n = map(int, input().split())
k = int(input())
p = [i for i in range(m*n + 1)] # 建立地图
for i in range(k): # 输入参数
    x,y = map(int, input().split())
    union(x,y) # 建立合根关系
ans = 0 # 根数标记

for i in range(1, m*n+1):
    if root(p[i]) == i: # 如果一个植物他的根是它本身的话,那这里就是一个根
        ans += 1
print(ans)

修改数组:

def root(x):
    if p[x] != x:
        p[x] = root(p[x])
    return p[x]
def union(x,y):
    if root(x) != root(y):
        p[root(x)] = root(y)

n = int(input())
li = list(map(int, input().split()))
p = [i for i in range(1000001)]
for i in range(n):
    li[i] = root(li[i])
    p[li[i]] = root(li[i] + 1)

for i in range(n):
    print(li[i], end=' ')

搜索:

个人感觉搜索无论是DFS还是BFS,做题是一定要抓住四个字:由易到难.两个搜索算法的模板并不复杂.

模板如下:

BFS(广度优先搜索)

while res:
	# 退出条件
	if 到达目标结点:
		break
	
	# 遍历四个搜索方向
	for i in range(4):
		if 满足所需要求:
			将该结点相关信息添加到 res 中
	
	# 该结点搜索完毕,删去信息
	res.pop(0)

DFS(深度优先搜索)

 
def dfs(参数):
    if (越界不合法情况):
        return
    if (终点边界,输出答案):
        return
    for (循环枚举所有方案):  
      if(未被标记): # if (越界不合法情况): 也可以放这一块写
        (标记)
        dfs(下一层)
        (还原标记) #回溯

所以我认为,此类题目我们应该从易到难:即,先从建立输入输出开始,随后步步厘清题目对数据的处理逻辑,并搭建相关的代码,最终调试结果.(着急你就输了QAQ)

例题如下:

危险系数(这题比较奇怪,同样的编辑器,我在蓝桥杯官方上就是100%样例通过,但在蓝桥云课上却只有80%的样例通过)

'''
m,n 站点数与通道数
mat 表示着地道地图
u v 代表着起点和重点
visited 函数表示着是否经过某点
path 代表路过某点的路径数
'''
def dfs(u, v):
    global path
    if u == v:
        # 每过一次,路径数加一次
        for i in range(n):
            if visited[i] == True:
                path[i] += 1
        return
    for i in range(n):
        if mat[u][i] == 1 and not visited[i]:
            visited[i] = True
            dfs(i, v) # 每遍历一个点都要遍历一遍他的可能经过的点
            visited[i] = False # 回溯

n, m = map(int, input().split())
mat = [[0 for j in range(n)] for i in range(n)]

for i in range(m):
    a,b = map(int, input().split())
    mat[a-1][b-1] = 1
    mat[b-1][a-1] = 1

u, v = map(int, input().split())
u, v = u - 1, v-1
visited = [False for i in range(n)]
path = [0 for i in range(n)]

dfs(u, v)
print(path.count(path[v]) - 1)

学霸的迷宫

题目:

# 广度优先搜索
n, m = map(int, input().split())
mp = [list(map(int, input())) for i in range(n)]

# visited用来记录结点访问状态
visited = [[False for j in range(m)] for i in range(n)]
visited[0][0] = True

# dx, dy 表示 下左右上 方向的坐标变动
d = ['D', 'L', 'R', 'U']
dx = [1, 0, 0, -1]
dy = [0, -1, 1, 0]

# res 用来记录当前搜索层结点的结果
# res[0][0] 表示横坐标
# res[0][1] 表示纵坐标
# res[0][2] 表示到达该结点的移动次数
# res[0][3] 表示到达该结点的路径
res = [[0, 0, 0, []]]

while res:
    # 终止条件:到达目标结点
    if (res[0][0] == n-1) and (res[0][1] == m-1):
        print(res[0][2])
        print(''.join(res[0][3]))

    # 遍历四个方向
    for i in range(4):
        new_x = res[0][0] + dx[i]
        new_y = res[0][1] + dy[i]
        new_path = res[0][3] + [d[i]]

        # 如果新坐标不超过边界
        if (0 <= new_x <= n-1) and (0 <= new_y <= m-1):
            # 如果该结点没有被访问过,且可以通过
            if (not visited[new_x][new_y]) and mp[res[0][0]][res[0][1]] == 0:
                res.append([new_x, new_y, res[0][2]+1, new_path])
                visited[new_x][new_y] = True

    # 该结点搜索完毕
    res.pop(0)

穿越雷区(60%):主要思路与上一题类似(个人感觉这一题比上一题要简单一些)

n = int(input())
mat = [list(input().split()) for i in range(n)]

visited = [[False for j in range(n)] for i in range(n)]
visited[0][0] = True

dx = [-1, 1, 0, 0]
dy = [0, 0 , 1, -1]

res = [[0, 0, 0]]

while res:
    if mat[res[0][0]][res[0][1]] == 'B':
        print(res[0][2])
        break
    for i in range(4):
        new_x = res[0][0] + dx[i]
        new_y = res[0][1] + dy[i]

        if (0 <=new_x <= n-1) and (0 <=new_y <= n-1):
            if (not visited[new_x][new_y]) and mat[res[0][0]][res[0][1]] !=mat[new_x][new_y]:
                res.append([new_x, new_y, res[0][2]+1])
                visited[new_x][new_y] = True
    res.pop(0)
if len(mat) == 0:
    print('-1')

本周总结:

本周终于是将将入门搜索算法了杂七杂八的题做了约有将近二十道了,距离蓝桥杯也只有两周时间了,我的心情也愈发忐忑.每天我都会不由自主的问自己,自己真的尽力了吗?自己真的又在努力学了吗?凡此种种,不胜枚举.突然有一天,我想到: 如果自己蓝桥杯到头来,没能拿到奖项,自己没能发挥好自己会怎样?会后悔懊恼嘛?我的心声告诉我: 会! 会放弃在计算机这条路上继续学下去嘛(毕竟自己也只是个非科班的鼠鼠orz)? 我毫不犹豫的想到: 绝对不会! 

蓝桥杯的奖项,可能最终我忙活到最后一秒,也只会是个省三(甚至省三都没有,这都是很有可能发生的),但是我仍然不会觉得这段备赛的经历,是无用的,我遇到了形形色色的人,结交到了志同道合的朋友.这才是我最大的收获. 当你重新踏上旅途之后,一定要记得旅途本身的意义.游戏同理,学习同理,人生更是同理

纵使困顿难行,应当砥砺奋进!!!!

诸君两周后见

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值