BFS解决全球变暖,找高地(DFS解题思路类似)
![](https://i-blog.csdnimg.cn/blog_migrate/6040ba7e2441db04614b8d565b161ca4.png)
import sys
sys.setrecursionlimit(300000) # 设置最大递归深度,默认递归深度有点小,不设置递归会出问题
from collections import *
def bfs(x,y):
global flag #判断是否有高地
q = deque() #队列
q.append((x,y))
vis[x][y]=1
while q:
x,y = q.popleft() #首元素出站
if mp[x][y+1]=='#' and mp[x][y-1]=='#' and \
mp[x+1][y]=='#' and mp[x-1][y]=='#':
flag = 1
for u,v in [(0,1),(0,-1),(1,0),(-1,0)]: # BFS遍历
nx = x+u ;ny = y+v
if vis[nx][ny]==0 and mp[nx][ny]=='#':
q.append((nx,ny))
vis[nx][ny]=1
def dfs(x,y):
d=[(-1,0),(0,1),(1,0),(0,-1)] # 左 上 右 下
global flag
global vis # 判断是否走过
global mp # 地图
vis[x][y] =1 #找连通分量不需要恢复现场
if mp[x][y+1]=='#' and mp[x][y-1] =='#' and mp[x+1][y]=='#' and mp[x-1][y]=='#':
# 说明点(x,y)四周都是陆地
flag = 1 # 高地标记,不会被淹没
for i in range(4):
nx=x+d[i][0]
ny=y+d[i][1]
if vis[nx][ny] ==0 and mp[nx][ny] =='#':
# 如果当前没有遍历点(nx,ny)同时地图上面该点不是陆地
dfs(nx,ny)
#----------------------------------------------------------------------------------#
n = int(input())
mp =[] # 存地图
for i in range(n):
mp.append(list(input()))
vis = [] # 判断是否到达过矩阵
for i in range(n):
vis.append([0]*n)
ans = 0
for i in range(n):
for j in range(n):
if vis[i][j]==0 and mp[i][j]=='#': #找陆地的连通分量
flag = 0
#bfs(i,j) # 找到一个连通分量,看是否有高地
dfs(i,j)
if flag ==0:
ans+=1
print(ans)
DFS排序加BFS搜索
![](https://i-blog.csdnimg.cn/blog_migrate/0382c767e58c9b00808d8428a68492d0.png)
import sys
sys.setrecursionlimit(300000) # 设置最大递归深度,默认递归深度有点小,不设置递归会出问题
from collections import *
def bfs():
vis = [0]*5 # 5个数的状态,判断是否用队列处理过
p=0
q=deque()
q.append(0) # 第一个进队列的数
vis[0]=1 # 表示0用队列处理过了
while not q:
i = q.popleft() # 出队列
p+=1
for j in range(5):
if vis[j]==0: # j没有用队列处理过
for k in (-1,1,-5,5): # 上下左右四个方向
if a[i]+k==a[j]: # 与j在k方向连通
q.append(j) # 将j添加进队列
vis[j]=1 # 进队列
if p==5:
return True
else :
return False
def perm(s,t): # 通过dfs生成全排列
global num
if s==5:
if bfs()==True : num+=1 # 得到5个数的排列,用BFS判断是否连通
else:
for i in range(s,t+1):
a[s],a[i]=a[i],a[s]
perm(s+1,t)
a[i],a[s] = a[s],a[i]
a=[1,2,3,4,6,7,8,9,11,12,13,14]
num=0
perm(0,11)
print(num//120) # num/5! = num//120
BFS搜索
![](https://i-blog.csdnimg.cn/blog_migrate/fe6a6e7e73cc88107c3bde427ac2f30a.png)
import sys
sys.setrecursionlimit(300000) # 设置最大递归深度,默认递归深度有点小,不设置递归会出问题
from collections import *
def insertQueue(q,dir,news,vis):
pos = news[1]
status = news[0]
insertPos = (pos +dir +9) % 9
# 将字符串转为列表比较好处理
t = list(status)
t[pos],t[insertPos] = t[insertPos],t[pos]
addStatus = "".join(t)
if addStatus not in vis:
vis[addStatus]=1 #向字典添加,用去重作用
q.append((addStatus,insertPos,news[2]+1))
q = [("012345678",0,0)]
vis = {"012345678":1} #字典
while q:
news = q.pop(0)
if news[0] =="087654321": #找到了目标状态,输出最少步数
print(news[2])
break
insertQueue(q,-2,news,vis) # 扩展下一层的4种情况
insertQueue(q,-1,news,vis) # 扩展下一层的4种情况
insertQueue(q, 1,news,vis) # 扩展下一层的4种情况
insertQueue(q, 2,news,vis) # 扩展下一层的4种情况
感悟:找路径需要恢复现场,找连通分量不需要恢复现场!!!