Leetcode 317. Shortest Distance from All Buildings

#include <vector>
#include <iostream>
#include <climits>
#include <queue>
using namespace std;

/*
  You want to build a house on an empty land which reaches all buildings in the shortest amount of distance. You can only move up, down, left and right. You are given a 2D grid of values 0, 1 or 2, where:

Each 0 marks an empty land which you can pass by freely.
Each 1 marks a building which you cannot pass through.
Each 2 marks an obstacle which you cannot pass through.
For example, given three buildings at (0,0), (0,4), (2,2), and an obstacle at (0,2):

1 - 0 - 2 - 0 - 1
|   |   |   |   |
0 - 0 - 0 - 0 - 0
|   |   |   |   |
0 - 0 - 1 - 0 - 0
The point (1,2) is an ideal empty land to build a house, as the total travel distance of 3+3+1=7 is minimal. So return 7.

Note:
There will be at least one building. If it is not possible to build such house according to the above rules, return -1.
*/

/*
Analyze:
   we start from "1" value and write down the steps to reach each node. If the node is reachable, we remember the reachable status as "-1". Thus, we need to maintain two tables. One is to remember the steps, the other to remember the reachable status.
*/
// canAchieve value mark the achievable nodes layerly. If the node is not achievable, it will always be '0'.

void BFS(vector< vector<int> >& grid, int i, int j, vector< vector<int> >& steps, vector< vector<int> >& canReach, int& canAchieve) {
  int m = grid.size();
  int n = grid[0].size();
  struct posAndStep {
    int x;
    int y;
    posAndStep(int k, int h) : x(k), y(h) {};
  };
  vector< vector<int> > tmpStep(m, vector<int>(n, 0));
  vector< vector<int> > dir {
  {0, 1},
  {0, -1},
  {1, 0},
  {-1, 0}};
  queue<posAndStep> nodes;
  posAndStep start(i, j);
  nodes.push(start);
  while(!nodes.empty()) {
    auto curr = nodes.front();
    nodes.pop();
    for(auto direction : dir) {
      int next_x = curr.x + direction[0];
      int next_y = curr.y + direction[1];
      if(next_x < m && next_x >= 0 && next_y < n && next_y >= 0 && (canReach[next_x][next_y] == canAchieve)) {
        --canReach[next_x][next_y];
        posAndStep next_node(next_x, next_y);
        tmpStep[next_x][next_y] = tmpStep[curr.x][curr.y] + 1;
        steps[next_x][next_y] += tmpStep[next_x][next_y];
        nodes.push(next_node);
      }
    }
  }
  --canAchieve;
}

int shortestDistance(vector< vector<int> >& grid) {
  if(grid.size() == 0 || grid[0].size() == 0) return 0;
  int m = grid.size();
  int n = grid[0].size();
  vector< vector<int> > steps(m, vector<int>(n, 0));
  vector< vector<int> > canReach = grid;
  // BFS to cacualte the step and remember the status.
  int canAchieve = 0;
  for(int i = 0; i < m; ++i) {
    for(int j = 0; j < n; ++j) {
      if(grid[i][j] == 1) {
        BFS(grid, i, j, steps, canReach, canAchieve);
      }
    }
  }
  int minDistant = INT_MAX;
  for(int i = 0; i < m; ++i) {
    for(int j = 0; j < n; ++j) {
      if(steps[i][j] && canReach[i][j]) {
        minDistant = min(minDistant, steps[i][j]);
      }
    }
  }
  return minDistant;
}

int main(void) {
  vector< vector<int> > matrix{
    {1, 0, 2, 0, 1},
    {0, 0, 0, 0, 0},
    {0, 0, 1, 0, 0}};
  cout << shortestDistance(matrix) << endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值