洪水覆盖算法(Flood Fill)
AcWing 1097. 池塘计数
https://www.acwing.com/problem/content/1099/
from collections import deque
xdis = [-1,1,0,0,-1,1,-1,1]
ydis = [0,0,-1,1,-1,-1,1,1]
def bfs(x,y):
dq = deque([[x,y]])
maze[x][y] = '.'
while dq:
x,y = dq.popleft()
for i in range(8):
x1 = x+xdis[i]
y1 = y+ydis[i]
if x1<1 or x1>n or y1<1 or y1>m:
continue
if maze[x1][y1] =='.':
continue
dq.append([x1,y1])
maze[x1][y1] = '.'
n,m = map(int,input().split())
maze = [['.'] for i in range(n+1)]
for i in range(n):
maze[i+1].extend(list(input()))
res = 0
for i in range(1,n+1):
for j in range(1,m+1):
if maze[i][j]=='W':
# print(i,j)
res += 1
bfs(i,j)
# print(maze)
print(res)
AcWing 1098. 城堡问题
https://www.acwing.com/problem/content/1100/
from collections import deque
xdirs = [0,-1,0,1]
ydirs = [-1,0,1,0]
def bfs(x,y):
dq = deque([[x,y]])
visited[x][y] = 1
ans = 1
while dq:
x,y = dq.popleft()
for i in range(4):
if not maze[x][y]>>i & 1:
x1,y1 = x+xdirs[i],y+ydirs[i]
if visited[x1][y1]:
continue
ans += 1
dq.append((x1,y1))
visited[x1][y1] = 1
return ans
n,m = map(int,input().split())
visited = [[0]*(m+1) for i in range(n+1)]
maze = [[0] for i in range(n+1)]
for i in range(n):
maze[i+1].extend(list(map(int,input().split())))
res = 0
ans = 0
for i in range(1,n+1):
for j in range(1,m+1):
if not visited[i][j]:
ans = max(ans,bfs(i,j))
res += 1
# bfs(1,1)
print(res)
print(ans)
AcWing 1106. 山峰和山谷
https://www.acwing.com/problem/content/1108/
from collections import deque
xdirs = [0, 0, 1, -1, 1, -1, 1, -1]
ydirs = [1, -1, 0, 0, 1, -1, -1, 1]
def bfs(x, y):
global max_res, min_res
num = maze[x][y]
dq = deque([[x, y]])
visited[x][y] = 1
is_min = True
is_max = True
while dq:
x, y = dq.popleft()
for i in range(8):
x1, y1 = x + xdirs[i], y + ydirs[i]
if x1 < 1 or x1 > n or y1 < 1 or y1 > n:
continue
if is_max and maze[x1][y1] > num:
is_max = False
if is_min and maze[x1][y1] < num:
is_min = False
if maze[x1][y1] == num and not visited[x1][y1]:
visited[x1][y1] = True
dq.append((x1, y1))
if is_min:
min_res += 1
if is_max:
max_res += 1
n = int(input())
maze = [[0] for i in range(n + 1)]
visited = [[0] * (n + 1) for i in range(n + 1)]
max_res = 0
min_res = 0
for i in range(n):
maze[i + 1].extend(list(map(int, input().split())))
for i in range(1, n + 1):
for j in range(1, n + 1):
if not visited[i][j]:
bfs(i, j)
print(max_res, min_res)
最短路模型
AcWing 1076. 迷宫问题
https://www.acwing.com/problem/content/1078/
from collections import deque
xdirs = [0,0,-1,1]
ydirs = [1,-1,0,0]
def bfs(x,y):
dq = deque([[x,y]])
maze[x][y] = 1
while dq:
x,y = dq.popleft()
for i in range(4):
x1,y1 = x+xdirs[i],y+ydirs[i]
if x1<0 or x1>=n or y1<0 or y1>=n or maze[x1][y1]==1:
continue
maze[x1][y1] = 1
dq.append((x1,y1))
path[x1][y1] = (x,y)
n = int(input())
maze = []
path = [[None]*n for i in range(n)]
for i in range(n):
maze.append(list(map(int,input().split())))
bfs(n-1,n-1)
i,j = 0,0
while True:
if i==n-1 and j==n-1:
break
print(i,j)
i,j = path[i][j]
print(n-1,n-1)
# print(path)
AcWing 188. 武士风度的牛
https://www.acwing.com/problem/content/190/
from collections import deque
xdirs = [-1,-1,1,1,-2,-2,2,2]
ydirs = [2,-2,2,-2,1,-1,1,-1]
def bfs(x,y):
dq = deque([[x,y]])
maze[x][y] = '*'
while dq:
x,y = dq.popleft()
for i in range(8):
x1,y1 = x+xdirs[i],y+ydirs[i]
if x1<0 or x1>=n or y1<0 or y1>=m or maze[x1][y1]=='*':
continue
maze[x1][y1] = '*'
cnt[x1][y1] = cnt[x][y]+1
dq.append((x1,y1))
m,n = map(int,input().split())
maze = []
cnt = [[0]*m for i in range(n)]
for i in range(n):
maze.append(list(input()))
# print(maze)
for i in range(n):
for j in range(m):
if maze[i][j]=='H':
res = (i,j)
for i in range(n):
for j in range(m):
if maze[i][j]=='K':
bfs(i,j)
print(cnt[res[0]][res[1]])
AcWing 1100. 抓住那头牛
https://www.acwing.com/problem/content/1102/
from collections import deque
xdirs = {
lambda x:x-1,
lambda x:x+1,
lambda x:x*2
}
N,K = map(int,input().split())
maze = [0 for i in range(100050)]
dq = deque()
dq.append(N)
maze[N] = 1
while dq:
x = dq.popleft()
if x == K:
break
for xdi in xdirs:
x1 = xdi(x)
if x1<0 or x1>=100050 or maze[x1]:
continue
maze[x1] = maze[x]+1
dq.append(x1)
# print(maze)
print(maze[K]-1)
多源BFS
AcWing 173. 矩阵距离
https://www.acwing.com/problem/content/175/
from collections import deque
xdirs = [0,0,1,-1]
ydirs = [1,-1,0,0]
def bfs():
is_visited = [[0]*m for i in range(n)]
dq = deque()
for i in range(n):
for j in range(m):
if maze[i][j]=='1':
dq.append((i,j))
is_visited[i][j] = 1
while dq:
x,y = dq.popleft()
for i in range(4):
x1,y1 = x+xdirs[i],y+ydirs[i]
if x1<0 or x1>=n or y1<0 or y1>=m or is_visited[x1][y1] or maze[x1][y1]=='1':
continue
cnt[x1][y1] = cnt[x][y]+1
dq.append((x1,y1))
is_visited[x1][y1] = 1
n,m = map(int,input().split())
maze = [list(input()) for i in range(n)]
cnt = [[0]*m for i in range(n)]
bfs()
for i in range(n):
print(*cnt[i])
最小步数模型
AcWing 1107. 魔板
https://www.acwing.com/problem/content/1109/
from collections import deque
def A(li):
lis = li[::-1]
return lis
def B(li):
lis = (li[3],)+li[:3]+li[5:8]+(li[4],)
return lis
def C(li):
lis = []
lis.append(li[0])
lis.append(li[6])
lis.append(li[1])
lis.append(li[3])
lis.append(li[4])
lis.append(li[2])
lis.append(li[5])
lis.append(li[7])
return tuple(lis)
start = tuple(map(int,input().split()))
d = {}
dq = deque()
dq.append((1,2,3,4,5,6,7,8))
d[(1,2,3,4,5,6,7,8)] = ('',None)
while dq:
s = dq.popleft()
if s==start:
break
s1 = A(s)
if s1 not in d:
dq.append(s1)
d[s1] = ('A',s)
s2 = B(s)
if s2 not in d:
dq.append(s2)
d[s2] = ('B',s)
s3 = C(s)
if s3 not in d:
dq.append(s3)
d[s3] = ('C',s)
cnt = 0
res = ''
# print(d)
s = (1,2,3,4,5,6,7,8)
while s != start:
cnt += 1
res += d[start][0]
start = d[start][1]
print(cnt)
if cnt:
print(res[::-1])
双端队列广搜
AcWing 175. 电路维修
https://www.acwing.com/problem/content/177/
from collections import deque
xdirs = [1,1,-1,-1]
ydirs = [1,-1,1,-1]
xi = [0,0,-1,-1]
yi = [0,-1,0,-1]
ma = ['\\','/','/','\\']
def bfs():
x,y = 0,0
dq = deque()
dq.append((x,y))
while dq:
x,y = dq.popleft()
if x==n and y==m:
return dist[x][y]
if visited[x][y]:
continue
visited[x][y] = True
for i in range(4):
x1,y1 = x+xdirs[i],y+ydirs[i]
if x1<0 or x1>n or y1<0 or y1>m:
continue
x2,y2 = x+xi[i],y+yi[i]
w = maze[x2][y2] != ma[i]
if dist[x1][y1]>dist[x][y]+w:
dist[x1][y1] = dist[x][y]+w
if not w:
dq.appendleft((x1,y1))
else:
dq.append((x1,y1))
T = int(input())
for _ in range(T):
maze = []
n,m = map(int,input().split())
for i in range(n):
maze.append(list(input()))
visited = [[False]*(m+1) for i in range(n+1)]
dist = [[float('inf')]*(m+1) for i in range(n+1)]
dist[0][0] = 0
if (m+n)%2:
print('NO SOLUTION')
else:
res = bfs()
print(res)
双向广搜
AcWing 190. 字串变换
https://www.acwing.com/problem/content/192/
import sys
from collections import deque
def check(dq, da, db, a, b):
# 每次只搜一层
# for i in range(len(dq)):
d = da[dq[0]]
while dq and da[dq[0]] == d:
s = dq.popleft()
for di in zip(a, b):
idx = -1
while idx < len(s):
idx = s.find(di[0], idx + 1)
if idx == -1:
break
new_s = s[:idx] + s[idx:].replace(di[0], di[1], 1)
if new_s in db:
return da[s] + 1 + db[new_s]
if new_s not in da:
# print(new_s)
da[new_s] = da[s] + 1
dq.append(new_s)
return 11
def bfs():
if start == end:
return 0
start_dq = deque()
end_dq = deque()
sdic = {}
edic = {}
sdic[start] = 0
edic[end] = 0
start_dq.append(start)
end_dq.append(end)
step = 0
while start_dq and end_dq:
if len(start_dq) < len(end_dq):
t = check(start_dq, sdic, edic, a, b)
else:
t = check(end_dq, edic, sdic, b, a)
if t <= 10:
return t
step += 1
if step == 10:
return -1
return -1
start, end = input().split()
a = []
b = []
for line in sys.stdin:
u, v = line.split()
a.append(u)
b.append(v)
res = bfs()
if res != -1:
print(res)
else:
print('NO ANSWER!')
A*算法
AcWing 178. 第K短路
https://www.acwing.com/problem/content/180/
import heapq
def djs(u):
dist[u] = 0
hp = []
heapq.heappush(hp,(0,u))
visited = [False for i in range(N+1)]
while hp:
u = heapq.heappop(hp)[1]
if visited[u]:
continue
visited[u] = True
for v,w in D[u]:
if dist[u]+w<dist[v]:
dist[v] = dist[u]+w
heapq.heappush(hp,(dist[v],v))
def Astar(S):
hp = []
heapq.heappush(hp,(dist[S],(0,S)))
while hp:
dis,u = heapq.heappop(hp)[1]
cnt[u]+=1
if cnt[T]==K:
return dis
for v,w in G[u]:
if cnt[v]<K:
heapq.heappush(hp,(dis+w+dist[v],(dis+w,v)))
return -1
N,M = map(int,input().split())
G = [[] for i in range(N+1)]
D = [[] for i in range(N+1)]
for i in range(M):
u,v,w = map(int,input().split())
G[u].append((v,w))
# 反向迪杰斯特拉邻接表
D[v].append((u,w))
S,T,K = map(int,input().split())
dist = [float('inf') for i in range(N+1)]
djs(T)
cnt = [0 for i in range(N+1)]
# print(dist)
# 去除等于0直接输出的这个方案
if S==T:
K+=1
print(Astar(S))
AcWing 179. 八数码
https://www.acwing.com/problem/content/181/
import heapq
def f(lis):
res = 0
for i in range(9):
if lis[i]=='x':
continue
res += abs(i//3-(int(lis[i])-1)//3)+abs(i%3-((int(lis[i])-1)%3))
return res
def bfs():
dist = {}
# 操作actions,上一个字符串
prev = {}
hp = []
heapq.heappush(hp,(f(start),start))
dist[tuple(start)] = 0
while hp:
lis = heapq.heappop(hp)[1]
if lis==end:
break
idx = lis.index('x')
x,y = idx//3,idx%3
pre_lis = lis[:]
t_pre_lis = tuple(pre_lis)
for i in range(4):
x1,y1 = x+xdis[i],y+ydis[i]
if x1<0 or y1<0 or x1>=3 or y1>=3:
continue
lis[x*3+y],lis[x1*3+y1] = lis[x1*3+y1],lis[x*3+y]
t_lis = tuple(lis)
if t_lis not in dist or dist[t_lis]>dist[t_pre_lis]+1:
dist[t_lis]=dist[t_pre_lis]+1
prev[t_lis] = (actions[i],t_pre_lis)
heapq.heappush(hp,(dist[t_lis]+f(lis),lis[:]))
lis[x*3+y],lis[x1*3+y1] = lis[x1*3+y1],lis[x*3+y]
res = ''
t_start = tuple(start)
t_end = tuple(end)
while t_start!=t_end:
res = prev[t_end][0]+res
t_end = prev[t_end][1]
return res
actions = "urdl"
xdis = [-1,1,0,0]
ydis = [0,0,-1,1]
start = input().split()
end = list('12345678x')
cnt = 0
idx = start.index('x')
s = start[:idx]+start[idx+1:]
for i in range(8):
for j in range(i+1,8):
if s[i]>s[j]:
cnt += 1
if cnt%2!=0:
print('unsolvable')
else:
print(bfs())