这是一道Dijkstra算法经典变形题!!!
题目描述
题目分析
代码同dj算法
- 数据结构:boolean visited[] + 优先队列
- 先把四个边加入优先队列,因为他们不能蓄水
- 每个点蓄水量==四周路径高度的最小值(路径高度定义为从该点出发到某个边界点的路径的最大高度)
- 入队(也叫松弛操作)即最优
- 贪心:每次最小高度的点出队,此时他的邻接点的最小路径高度的路径方向是刚出队的点
- 从四边界不断往图的中心收缩,也可以理解为入队的点一开始是边界后来是图中较中心点,也可以理解为图的边界不断缩小包围圈
python实现
class Solution:
def trapRainWater(self, heightMap: List[List[int]]) -> int:
def get(x,y)->Generator[Tuple[int,int],None,None]:
if x+1<m:yield (x+1,y)
if x>0:yield (x-1,y)
if y+1<n:yield (x,y+1)
if y>0:yield (x,y-1)
ans = 0
pq = []
vis = set()
m = len(heightMap)
n = len(heightMap[0])
for i in range(n):
heapq.heappush(pq,(heightMap[0][i],0,i))
vis.add((0,i))
heapq.heappush(pq,(heightMap[m-1][i],m-1,i))
vis.add((m-1,i))
for i in range(1,m-1):
heapq.heappush(pq,(heightMap[i][0],i,0))
vis.add((i,0))
heapq.heappush(pq,(heightMap[i][n-1],i,n-1))
vis.add((i,n-1))
while pq:
tmp,x,y = heapq.heappop(pq)
for nx,ny in get(x,y):
if (nx,ny) not in vis:
if heightMap[nx][ny]<tmp:
ans += tmp-heightMap[nx][ny]
heapq.heappush(pq,(max(heightMap[nx][ny],tmp),nx,ny))
vis.add((nx,ny))
return ans