撒水问题是我们经常遇到的bfs的问题,在多少时间能扩散多少,和全部扩散到要花多少时间,这也是多bfs问题,下面是我做dfs问题的思路。
一维问题 (农田灌溉)
面对一维扩散问题,我们先了解,它可以向前走或者向后走,将其扩散到全部放在一个单独的函数中,进行判断使用的最大的时间,
1.输入------------创一个函数存放该地所要的时间
n,k=map(int,input().split())
a=list(map(int,input().split()))
b=[float('-inf')]*(n+1)
for i in a:
b[i]=1
s=[-1,1]
2.进行bfs 算法进行广度遍历
这里要注意一点是,跳过已经遍历过的田地,因为原来算过的必定是最小的。
while a:
t=a.pop(0)
for i in s:
x=i+t
if 1<=x<=n and b[x]==float('-inf'): #跳过已经遍历过的只算该地区的最小值
b[x]=b[t]+1
a.append(x)
print(max(b))
二维扩散问题 (扩散)
这一道题要注意,用列表的话会发生超时,用python自带的队列进行计算,不过还是比较慢
1.输入
注意队列的时候不是仅仅是(x,y)在往后面加一个零,更方便我们对题目要求进行判断,什么时候可以跳出循环,类如题目给的2020次进行统计。ans是计算扩散的个数,跳出循环可以直接输出ans
import collections
dx = [-1, 1, 0, 0]
dy = [0, 0, 1, -1]
pre = {(0, 0): (0, 0), (2020, 11): (2020, 11), (11, 14): (11, 14), (2000, 2000): (2000, 2000)}
ans = 4
queue = collections.deque()
queue.append((0, 0, 0))
queue.append((2020, 11, 0))
queue.append((11, 14, 0))
queue.append((2000, 2000, 0))
bfs算法
当后面的0变成到2020时跳出循环,每扩散一次将其ans+=1
while queue:
t = queue.popleft()
if t[2] == 2020:
print(ans)
break
else:
for i in range(4):
nx, ny = t[0] + dx[i], t[1] + dy[i]
if (nx, ny) not in pre.keys():
pre[(nx, ny)] = (t[0], t[1])
queue.append((nx, ny, t[2] + 1))
ans += 1
print(ans)
方法二暴力算法
x = [0, 2020, 11, 2000]
y = [0, 11, 14, 2000]
res = 0
for i in range(-2020, 4041):
for j in range(-2020, 4041):
for z in range(0, 4):
if abs(x[z] - i) + abs(y[z] - j) <= 2020:
res += 1
break
print(res)
二维暴力算法 (灌溉)
实在不会做,可以考虑一下暴力解决,循环嘎嘎猛
暴力
1.输入
n,m=map(int,input().split())
t=int(input()) #2个出水口
a=[[0]*(m) for _ in range(n)] #初始的方格
b=[[0]*(m) for _ in range(n)] #灌溉后的方格
for i in range(t):
r,c=map(int,input().split())
a[r-1][c-1]=1 #初始化出水口
k=int(input())
2.暴力循环
for _ in range(k,0,-1): #一分钟灌溉一次
for i in range(n):
for j in range(m):
if a[i][j]==1:
b[i][j]=1 #中心值标记
if i-1>=0: #合格范围标记四个方向的水管
b[i-1][j]=1
if i+1<n:
b[i+1][j]=1
if j-1>=0:
b[i][j-1]=1
if j+1<m:
b[i][j+1]=1
a=b #灌溉完毕递归下一次
#输出
cnt=0
for i in b:
for j in i:
cnt+=j
print(cnt)
解决扩散问题