参考文章均为链接,题目描述请在链接中找(小声:看名字就能知道),作者整理自己的思路,方法与大佬不尽相同,可留意一下,代码分析在代码后面
注:偷懒了,偷懒了,明日非干两篇出来,啊啊啊啊啊啊
参考文章:【蓝桥杯真题】18天Python组冲刺 心得总结、扩展欧几里德算法、一步之遥——第七届蓝桥杯C语言B组(国赛)第一题、蓝桥杯2017年第八届真题-九宫幻方-题解(Python代码)、
1.一步之遥
本题大体上有三种方法:扩展欧几里得算法、暴力枚举和广搜,广搜解释在代码中
关于广搜,可查看 Python真题练习,其中第4题穿越雷区思路与其相似,代码几乎相同,两题对比着写一写,就大概会了广搜的单源最短路径了
#扩展欧几里得
def expand_gcd(a,b):
global x,y
if not b:
x,y=1,0
return a
else:
d=expand_gcd(b,a%b)
x,y=y,x-(a//b)*y
return d
b=expand_gcd(97,127)
print(abs(x//b)+abs(y//b))
扩展欧几里德算法描述为:已知a, b求解一组x,y,使它们满足贝祖等式: ax+by = gcd(a, b) =d,那么用文字描述为进行x次a,和y次b,到达d(a,b的最大公约数),题目要求最后到达的是1,即ax*+by*=1,就将刚才求出的x,y除以d,即x*=x/gcd(a,b),题目求的是操作次数,即为进行x*次的a和y*次的b的总和x*+y*
#+97 -127 =1
#类似于扩展欧几里得算法,求97x-127y=1的解中x+y最小,就是线性规划
max=float('inf')
for i in range(100):
for j in range(100):
if 97*i-127*j==1:
ans=min(i+j,max)
print(ans)
暴力枚举:就是线性规划,求97x-127y=1的解中x+y最小,双层遍历即可
#总结:单源最短路径BFS用到三个容器:方向数组、判断矩阵(或数组)、队列
# 方向数组储存单源行进的方向
# 判断矩阵记录某位置是否被访问过
# 队列记录当前位置和步数,当判断条件通过时添加上邻居的位置和步数
#方向数组,意为单个源头行进的方向
Move=[97,-127]
#判断字典,判断位置i是否被访问过,已访问过的显然无需再次访问
judge_matrix={}
for i in range(-1000,1000):
judge_matrix[i]=0
# print(judge_matrix)
#已知起始位置为0,当前步数为0,
#队列记录当前位置及已走的步数
queue=[(0,0)]
while queue:
#判断是否到达结束位置 1
if queue[0][0]==1:
print(queue[0][1])
for i in range(2):
next_location=queue[0][0]+Move[i]
#重点:这里判断 下一位置 不超出判断矩阵的判断范围
#一是避免判断矩阵过大浪费空间,
#二是没有必要设置过大空间,比如先加97*100,再加-127*100,
#同持续加一次97,和加一次-127,效果一样,
if -1000<next_location<1000 and not judge_matrix[next_location]:
queue.append([next_location,queue[0][1]+1])
judge_matrix[next_location]=1
queue.pop(0)
2.农田灌溉
代码中涉及的 bisect 模块,可在文章 二分查找、动态规划、深搜+广搜 找到
#先考虑一组测试数据,n块农田,k个洒水器
#1秒之后,含有洒水器的农田被灌溉
#那么对于其他的农田,记住它总是被距离它最近的洒水器先灌溉
#也就是问题转化为求没有洒水器的农田与距离它最近的洒水器的距离,用二分查找
#求出的一组距离取最大值就是所有农田均被灌溉的时间
import bisect
T=int(input())
def irrigate_time(n,k,sprinkler):
irrigation_distance=[float('inf') for _ in range(n)]
for i in range(k):
#1秒灌溉距离加1,这里就用距离代替时间,且含有洒水器的农田的灌溉距离为1
#洒水器起始位置为1,所以减去1,对于列表下标
irrigation_distance[sprinkler[i]-1]=1
#遍历所有初始灌溉距离不为1的农田,利用二分查找找出其灌溉距离
for j in range(n):
if irrigation_distance[j]!=1:
p=bisect.bisect_left(sprinkler,j+1)
right_min=sprinkler[p]-(j+1) if p<k else float('inf')
left_min=(j+1)-sprinkler[p-1] if p>0 else float('inf')
#显然洒水器与农田的灌溉距离要加上含有洒水器的农田的灌溉距离 1 ,至少得让有洒水器的那块田先被灌溉
irrigation_distance[j]=min(right_min+1,left_min+1)
print(max(irrigation_distance))
for i in range(T):
n,k=map(int,input().split())
sprinkler=list(map(int,input().split()))
sprinkler.sort()
irrigate_time(n,k,sprinkler)
#上面涉及的 bisect 模块,读者可在如下代码操作一下
# import bisect
# list=[1,3,5,7]
# j=bisect.bisect_left(list,6)
# print(j)
3.九宫幻方
#九宫格展开成一行,有八种形式,分别是从上下左右的各个方位正S、反S展开
empyreals=[
[4,9,2,3,5,7,8,1,6],
[2,9,4,7,5,3,6,1,8],
[8,3,4,1,5,9,6,7,2],
[4,3,8,9,5,1,2,7,6],
[2,7,6,9,5,1,4,3,8],
[6,7,2,1,5,9,8,3,4],
[6,1,8,7,5,3,2,9,4],
[8,1,6,3,5,7,4,9,2]
]
alist=[list(map(int,input().split())) for _ in range(3)]
#将二维列表转化为一维列表,两种方法
alist=[j for i in alist for j in i]
# from tkinter import _flatten
# clist=list(_flatten(alist))
ans_list=[]
for i in range(8):
#flag记录当前的九宫格是否符合输入的九宫格
flag=True
for j in range(9):
#先判断九宫格的每一个元素是否对应相等,相等的话符合,不相等有两种情况,
#一是元素被抹去为0,这种符合,另一种就是不为0且不相等,只有这种情况不符合
if alist[j]!=empyreals[i][j] and alist[j]!=0:
flag=False
break
if flag:
#记录符合条件的列表在 empyreals 中的下标
ans_list.append(i)
if len(ans_list)==1:
for k in range(9):
print(empyreals[ans_list[0]][k],end=' ')
if (k+1)%3==0:
#空出一行
print()
else:
print('Too Many')