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的應用(我覺得也是這道題的難點)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章