bfs-407. Trapping Rain Water II[Hard]

题目描述


Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevation map, compute the volume of water it is able to trap after raining.

Note:
Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000.

Example:

Given the following 3x6 height map:
[
  [1,4,3,1,3,2],
  [3,2,1,3,2,4],
  [2,3,3,2,3,1]
]

Return 4.


The above image represents the elevation map [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]] before the rain.


After the rain, water are trapped between the blocks. The total volume of water trapped is 4.


求出凹陷下去的地方能盛的水体积


解题思路

虽然是bfs的标签,但是因为第一次接触这种类型题,完全无思路(毕竟是hard),然后,发现了一位大神图文并茂的解题说明(感激!):

Grandyang的博客(我只是参考了解题思路,代码是自己写的)


一个方块能装水,那么它的四周都必须是比它高的方块,因此,bfs的应用就是,取出一个方块,遍历它外围的四块方块。然而,题目并不是那么简单。这道题还用到了优先队列(每次挑选高度最小的出队,和一般的bfs不一样,优先队列参考内容:ZXH小朋友的上学史 的博客)以及模拟海平面上升的方法(Grandyang 博客里有):海平面初始值为1,取出priorityqueue的top元素,若是 高度 > 海平面,则用这个值更新海平面,遍历元素四周的方块,低于海平面,则可装的水是海平面 - 方块高度。


好了,现在对整个解题过程进行总结:

一、主要准备:

1、priority queue (forBFS):装有最外围一圈方块,并以高度从小到大出队。

2、海平面(seaRevel):方块装水的参照,装水量:海平面 - 方块高度

3、代表元素坐标、高度的box

4、代表box四周方块的坐标偏移量pos{(1,0),(0,1),(-1,0),(0,-1)}(要注意越界问题)


二、核心思路:

出队一个box,判断四周方块是否被访问过,如果没有,把方块入队,置visited = true。判断遍历的方块与海平面的关系,能装的水:海平面 - 方块高度。



代码如下:


class Solution {
public:
    struct Box {
	int x;
	int y;
	int height;

	Box(int a, int b, int c) :x(a), y(b), height(c) {

	}

	bool operator < (const Box& b) const {

		return b.height < height;
	}
};
    int trapRainWater(vector<vector<int>>& heightMap) {
      if (heightMap.size() == 0) {
		return 0;
	}

	int rowCount = heightMap.size();
	int colCount = heightMap[0].size();

	priority_queue<Box> forBFS;

	vector<bool> tmp(colCount, false);
	vector<vector<bool> >visited(rowCount, tmp);

	for (int i = 0; i < colCount; i++) {

		if (!visited[0][i]) {
			forBFS.push(Box(0, i, heightMap[0][i]));
			visited[0][i] = true;
		}

		if (!visited[rowCount - 1][i]) {
		forBFS.push(Box(rowCount - 1, i, heightMap[rowCount - 1][i]));
		visited[rowCount - 1][i] = true;
		}
	}
	for (int j = 0; j < rowCount; j++) {
		if (!visited[j][0]) {
			forBFS.push(Box(j, 0, heightMap[j][0]));
			visited[j][0] = true;
		}

		if (!visited[j][colCount - 1]) {
			forBFS.push(Box(j, colCount - 1, heightMap[j][colCount - 1]));
			visited[j][colCount - 1] = true;
		}

	}

	int seaRevel = 0;
	int water = 0;

	vector<pair<int, int> > pos;
	pos.push_back(pair<int, int>(0, 1));
	pos.push_back(pair<int, int>(1, 0));
	pos.push_back(pair<int, int>(0, -1));
	pos.push_back(pair<int, int>(-1, 0));

	while (!forBFS.empty()) {
		Box now = forBFS.top();
		forBFS.pop();
		
		if (seaRevel < now.height)
			seaRevel = now.height;

			

			for (int i = 0; i < 4; i++) {
				pair<int, int> next = pos[i];
				int nextX = now.x + next.first;
				int nextY = now.y + next.second;

				if (nextX < 0 || nextY < 0)
					continue;
				if (nextX >= rowCount || nextY >= colCount)
					continue;

				if (!visited[nextX][nextY]) {

					water = seaRevel > heightMap[nextX][nextY] ? water + (seaRevel - heightMap[nextX][nextY]) : water + 0;
					forBFS.push(Box(nextX, nextY, heightMap[nextX][nextY]));
					visited[nextX][nextY] = true;

				}

			}

		

		



	}

	return water;
        
    }
};



感触:

1、优先队列的使用

2、vector的初始化方法,vector(numberOfElements,value),省去了memset的调用

3、bfs的应用(我觉得也是这道题的难点)

内容概要:本文详细介绍了“电动汽车聚合可行域的内-外结合近似方法”的Matlab代码实现,旨在通过数值仿真手段对大规模电动汽车集群作为灵活资源参与电网调度的能力边界进行建模与逼近。该方法融合内部凸包构造与外部约束逼近策略,精确刻画电动汽车在充电状态、功率调节、时间维度等方面的聚合可调能力范围,形成紧致的可行域表示,为高比例电动车接入下的电力系统优化调度、需求响应、车网互动(V2G)等关键应用提供可靠的建模基础。文中强调科研应兼顾严谨逻辑与创新思维,并倡导借助YALMIP等成熟优化工具提升研究效率。完整的代码、工具包及相关案例可通过指定网盘链接和微信公众号“荔枝科研社”获取。; 适合人群:具备电力系统分析、优化理论基础及Matlab编程能力的科研人员,尤其适用于从事新能源并网、电动汽车调度、智能电网、综合能源系统等方向的研究生与工程技术人员。; 使用场景及目标:①研究大规模电动汽车集群的聚合建模与灵活性量化方法;②实现电动汽车聚合可行域的内-外近似算法;③支撑含高渗透率电动汽车的电力系统日前-实时协同优化调度;④学习并应用YALMIP工具进行数学规划建模与求解;⑤为需求响应、市场机制设计及V2G运营提供技术支撑。; 阅读建议:建议读者按照文档指引循序渐进学习,结合网盘提供的完整资源(包括YALMIP工具包与示例代码)进行实践调试,重点掌握内-外近似方法的数学建模逻辑、约束处理技巧及优化求解流程,并参考团队发布的其他相关案例,深化对优化算法与仿真技术在能源系统中应用的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值