蓝桥杯备赛(六)-双指针、BFS、图论
概念
双指针:分为1.对撞指针:左右两个指针,向中间靠拢。2.滑动窗口等等。
BFS:宽度优先搜索,也是比较常用的算法。
图论:dddd,范围过于庞大。
实例
Q1
日志统计(原题链接)
A1
通过将日志排序,然后利用滑动窗口来限制时间区间。同时动态进行增加减即可。
代码如下:
n,d,k=map(int,input().split())
blog_lst=[]
s_lst=[0 for _ in range(int(1e5))]
cnt_lst=[0 for _ in range(int(1e5))]
for _ in range(n):
blog_lst.append(list(map(int,input().split())))
blog_lst.sort()
j=0
for i in range(n):
cnt_lst[blog_lst[i][1]]+=1
while blog_lst[i][0]-blog_lst[j][0]>=d:
cnt_lst[blog_lst[j][1]]-=1
j+=1
if cnt_lst[blog_lst[i][1]]>=k:
s_lst[blog_lst[i][1]]=1
for i in range(int(1e5)):
if s_lst[i]:
print(i)
Q2
献给阿尔吉侬的花束(原题链接)
A2
就是一个典型的bfs
代码如下:
from collections import deque
T=int(input())
dx=[0,1,0,-1]
dy=[-1,0,1,0]
def bfs(i,j):
#i,j:初始点
d=deque()
d.append([i,j])
while len(d):
a,b=d[-1]
d.pop()
mat[a][b]='#'
for i in range(4):
x=a+dx[i]
y=b+dy[i]
if (x>=0)&(x<r)&(y>=0)&(y<c):
if mat[x][y]!='#':
#没走过,要填入
d.appendleft([x,y])
dis_mat[x][y]=dis_mat[a][b]+1
if mat[x][y]=='E':
print(dis_mat[x][y])
return
mat[x][y]='#'
print('oop!')
while T:
r,c=map(int,input().split())
mat=[list(input()) for _ in range(r)]
dis_mat=[[0 for _ in range(c)] for _ in range(r)]
for i in range(r):
for j in range(c):
if mat[i][j]=='S':
bfs(i,j)
break
T-=1
Q3
交换瓶子(原题链接)
A3
形成自环。比较特殊,一般情况下难以想到。
代码如下:
n=int(input())
raw_list=list(map(int,input().split()))
have_list=[0 for i in range(n)]
cnt=0
#统计多少个环
for i in range(n):
if not have_list[i]:
cnt+=1
#此时来构造环
j=i
while not have_list[j]:
have_list[j]=1
j=raw_list[j]-1
print(n-cnt)
Q4
红与黑(原题链接)
A4
经典dfs和bfs。就是搜索。
代码如下:
#1113.红与黑
#典型的Bfs题目
from collections import deque
flag=1
while flag:
h,w=list(map(int,input().split()))[::-1]
if h==0|w==0:
break
floor_matrix=[list(input()) for _ in range(h)]
def bfs(i,j):
q=deque()
q.append([i,j])
cnt=1
floor_matrix[i][j]='#'
while len(q):
#进行bfs
a,b=q[-1]
q.pop()
dx=[0,1,0,-1]
dy=[-1,0,1,0]
for i in range(4):
x=a+dx[i]
y=b+dy[i]
if(x>=0)&(x<h)&(y>=0)&(y<w):
if floor_matrix[x][y]=='.':
q.appendleft([x,y])
cnt+=1
floor_matrix[x][y]='#'
print(cnt)
for i in range(h):
for j in range(w):
if floor_matrix[i][j]=='@':
bfs(i,j)
break
#我们也可以采取dfs来进行推理
#1113.红与黑
#典型的dfs题目
from collections import deque
flag=1
while flag:
h,w=list(map(int,input().split()))[::-1]
cnt=0
if h==0|w==0:
break
floor_matrix=[list(input()) for _ in range(h)]
def dfs(i,j):
global cnt
cnt+=1
floor_matrix[i][j]='#'
dx=[-1,0,1,0]
dy=[0,1,0,-1]
for t in range(4):
x=i+dx[t]
y=j+dy[t]
if (x>=0)&(x<h)&(y>=0)&(y<w):
if floor_matrix[x][y]=='.':
dfs(x,y)
for i in range(h):
for j in range(w):
if floor_matrix[i][j]=='@':
dfs(i,j)
print(cnt)
break
Q5
交换瓶子(原题链接)
A5
该题阔以利用双指针进行计算,同时也可以采用树状数组进行求解。但很明显复杂度后者高一个logn级别
代码如下:
#1240.完全二叉树的权值
#该题采用双指针算法进行运算,时间复杂度只有O(n)
n=int(input())
tr=list(map(int,input().split()))
"""
depth:层数
i:当前遍历起点
j:当前遍历终点
"""
depth=1
maxs=tr[0]
dd=1
while (1<<(depth-1))-1 <n:
s=0
i=2**(depth-1)
j=min(i+(1<<(depth-1)),n)
#print(i,j)
for t in range(i,j):
s+=tr[t-1]
if s>maxs:
maxs=s
dd=depth
depth+=1
print(dd)
#采取树状数组求解,也能完全AC
#1240.完全二叉树的权值
#采取树状数组(复杂度O(logn))
n=int(input())
raw_list=list(map(int,input().split()))
tr=[0 for i in range(n+1)]
def lowbit(x):
return x&-x
def add(x,v):
while x<=n:
tr[x]+=v
x+=lowbit(x)
def query(x):
if x==0:
return 0
sum_=0
while x:
sum_+=tr[x]
x-=lowbit(x)
return sum_
#初始化树状数组
for i in range(n):
add(i+1,raw_list[i])
depth=1
dd=1
maxsum=-1000000000
while ((1<<(depth-1))-1) <n:
s=query(min((1<<depth)-1,n))-query((1<<(depth-1))-1)
if maxsum<s:
maxsum=s
dd=depth
depth+=1
print(dd)
Q6
地牢大师(原题链接)
A6
三维的bfs,模板题
代码如下:
from collections import deque
dx=[-1,0,1,0,0,0]
dy=[0,0,0,0,1,-1]
dz=[0,1,0,-1,0,0]
def bfs(i,j,k):
d=deque()
d.append([i,j,k])
mat[i][j][k]='#'
while len(d):
a,b,c_=d[-1]
d.pop()
for i in range(6):
x,y,z=a+dx[i],b+dy[i],c_+dz[i]
if x>=0 and x<l and y>=0 and y<r and z>=0 and z<c:
if mat[x][y][z]!='#':
dis_mat[x][y][z]=dis_mat[a][b][c_]+1
d.appendleft([x,y,z])
if mat[x][y][z]=='E':
print('Escaped in {} minute(s).'.format(dis_mat[x][y][z]))
return
mat[x][y][z]='#'
print('Trapped!')
while True:
l,r,c=map(int,input().split())
if l==0:
break
mat=[]
for i in range(l):
mat.append([list(input()) for _ in range(r)])
_=input()
dis_mat=[[[0 for _ in range(c)]for _ in range(r)]for _ in range(l)]
for i in range(l):
for j in range(r):
for k in range(c):
if mat[i][j][k]=='S':
bfs(i,j,k)
break
Q8
全球变暖(原题链接)
A8
bfs的思想运用在这里,同时进行边界的判断,就可以运用了。
代码如下:
#1233.全球变暖
#利用bfs的思想,同时想到bound和count的关系
#注意这里的关系,需要将使用过的#置换为have,置换为'.'会导致影响check
from collections import deque
n=int(input())
map_mat=[list(input())for _ in range(n)]
cnt=0
dx=[-1,0,1,0]
dy=[0,1,0,-1]
def check(i,j):
for t in range(4):
x=i+dx[t]
y=j+dy[t]
if (x>=0)&(x<n)&(y>=0)&(y<n):
if map_mat[x][y]=='.':
return True
return False
def bfs(i,j):
global cnt
count=1
bound=1
q=deque()
q.append([i,j])
map_mat[i][j]='h'
while len(q):
a,b=q[-1]
q.pop()
for t in range(4):
x=a+dx[t]
y=b+dy[t]
if (x>=0)&(x<n)&(y>=0)&(y<n):
if map_mat[x][y]=='#':
q.appendleft([x,y])
count+=1
map_mat[x][y]='h'
if check(x,y):
bound+=1
if (bound==count):
cnt+=1
for i in range(n):
for j in range(n):
if map_mat[i][j]=='#':
bfs(i,j)
print(cnt)
Q9
大臣的旅费(原题链接)
A9
树的直径问题,dfs和bfs都行。但Python容易爆栈,故选用bfs.
代码如下:
from collections import deque
n=int(input())
E=[[]for _ in range(n)]
for _ in range(n-1):
p,q,d=map(int,input().split())
E[p-1].append([q-1,d])
E[q-1].append([p-1,d])
def bfs(index):
maxlen=0
maxfar=0
dis_lit=[-1]*n
dis_lit[index]=0
q=deque()
q.append(index)
while len(q):
index=q[-1]
q.pop()
for i in E[index]:
if dis_lit[i[0]]==-1:
#没有遍历过
q.appendleft(i[0])
dis_lit[i[0]]=dis_lit[index]+i[1]
maxlen=max(dis_lit)
maxfar=dis_lit.index(maxlen)
return maxlen,maxfar
_,end=bfs(0)
maxlen,_=bfs(end)
print(10*maxlen+maxlen*(maxlen+1)//2)
总结
难的雅痞