蓝桥杯第8天(Python组)

文章介绍了使用BFS广度优先搜索和DFS深度优先搜索来解决与全球变暖相关的地理问题,即寻找高地。通过对地图进行遍历,确定陆地的连通分量并判断是否存在高地。同时,文章强调了在递归深度限制和状态判断上的注意事项,并给出了示例代码进行解释。
摘要由CSDN通过智能技术生成
BFS解决全球变暖,找高地(DFS解题思路类似)
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搜索
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搜索
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种情况
  

感悟:找路径需要恢复现场,找连通分量不需要恢复现场!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值