刷题 | Lintcode 573. Build Post Office II 解题报告
[Problem]
Given a 2D grid, each cell is either a wall 2
, an house 1
or empty 0
(the number zero, one, two), find a place to build a post office so that the sum of the distance from the post office to all the houses is smallest.
Return the smallest sum of distance. Return -1
if it is not possible.
Notice
- You cannot pass through wall and house, but can pass through empty.
- You only build post office on an empty.
Example
Given a grid:
0 1 0 0 0
1 0 0 2 1
0 1 0 0 0
return 8
, You can build at (1,1)
. (Placing a post office at (1,1), the distance that post office to all the house sum is smallest.)
[Idea]
从房子的角度来看。也是用 BFS 来遍历所有的空地,不过这里就需要在每个空地中记录房子访问次数和房子距离之和了。记录访问次数是为了确保所有房子都能访问到该空地,否则就不是可行解。这种解法的优势是在于当房子数目远小于空地数目时比上面从空地出发进行 BFS 要更快一些。所以这也是一种权衡(trade-off)了,要视数据集的具体情况而定。
[Code]
class Node { public: Node(){} Node(int xx, int yy, int dist) { x = xx; y = yy; dis = dist; } int x, y, dis; }; class Solution { private: int dx[4] = {1,0,-1,0}; int dy[4] = {0,1,0,-1}; bool valid(int nx, int ny, int n, int m, vector<vector<int>>& grid, vector<vector<bool>>& visited) { if(0 <= nx && nx < n && 0 <= ny && ny < m) { if(grid[nx][ny] == 0 && visited[nx][ny] == false) { return true; } } return false; } void bfs(Node cur, vector<vector<int>>& grid, vector<vector<int>>& dis, vector<vector<int>>& visit_num, int n, int m) { queue<Node> q; q.push(cur); vector<vector<bool>> visited(n, vector<bool>(m)) ; while(!q.empty()) { cur = q.front(); q.pop(); visit_num[cur.x][cur.y]++; for(int i = 0; i < 4; i++) { int nx = cur.x + dx[i]; int ny = cur.y + dy[i]; if (valid(nx, ny, n, m, grid, visited)) { dis[nx][ny] = dis[nx][ny] + cur.dis + 1; visited[nx][ny] = true; q.push(Node(nx, ny, cur.dis+1)); } } } } public: /* * @param grid: a 2D grid * @return: An integer */ int shortestDistance(vector<vector<int>> &grid) { // write your code here if(grid.size() == 0) return 0; int n = grid.size(); int m = grid[0].size(); vector<vector<int>> dis(n, vector<int>(m, 0)); vector<vector<int> > visit_num(n, vector<int>(m)) ; int house_num = 0; for (int i = 0; i < grid.size(); i++) { for (int j = 0; j < grid[i].size(); j++) { if (grid[i][j] == 1) { house_num++; bfs(Node(i,j,0), grid, dis, visit_num, n, m); } } } int ans = INT_MAX; for (int i = 0; i < grid.size(); i++) { for(int j = 0; j < grid[i].size(); j++) { if (grid[i][j] == 0 && visit_num[i][j] == house_num){ ans = min(ans, dis[i][j]); } } } return ans == INT_MAX ? -1 : ans; } };
[Reference]