675. Cut Off Trees for Golf Event

// Potential improvements:
// 1. we can use vector<int> { h, x, y } to replace Element, sorting vector is to compare elements one by one.
// 2. use 2-d bool vector<vector<bool>> to replace unordered_set.

class Element {
public:
    int x, y, h;
    Element(int x, int y, int h) {
        this->x = x;
        this->y = y;
        this->h = h;
    }
};
class Solution {
public:
    int m;
    int n;
    int cutOffTree(vector<vector<int>>& forest) {
        m = forest.size();  if (m == 0) return 0;
        n = forest[0].size();   if (n == 0) return 0;
        vector<Element> v;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if (forest[i][j] > 1)
                    v.emplace_back(i, j, forest[i][j]);
        auto comp = [](const Element& a, const Element& b) { return a.h < b.h; };
        v.emplace_back(0, 0, 0);
        sort(v.begin(), v.end(), comp);
        
        int res = 0;
        for (int i = 0; i < v.size()  - 1; i++) {
            int t = helper(forest, v[i], v[i+1]);
            if (t < 0)  return t;
            res += t;
        }
        return res;
    }
    int helper(vector<vector<int>>& forest, const Element& a, const Element& b) {
        const int dirs[] = { -1, 0, 1, 0, -1 };
        // (x,y) is small enough, so x*n+y won't overflow. otherwise we have to use long,
        // and be careful x*n+y will overflow, we may use (long)x*n+y instead.
        unordered_set<int> s;   
        queue<pair<int,int>> q;
        q.push({a.x, a.y});
        s.insert(a.x * n + a.y);
        int lv = 0;
        while (!q.empty()) {
            int qsz = q.size();
            for (int i = 0; i < qsz; i++) {
                auto cur = q.front();
                q.pop();
                if (cur.first == b.x && cur.second == b.y)
                    return lv;
                for (int i = 0; i < 4; i++) {
                    int nx = cur.first + dirs[i];
                    int ny = cur.second + dirs[i+1];
                    pair<int,int> np = {nx,ny};
                    if (nx >= 0 && nx < m && ny >= 0 && ny < n && 
                        forest[nx][ny] > 0 &&
                        s.find(nx * n + ny) == s.end()) {
                        q.push(np);
                        s.insert(nx * n + ny);
                    }
                }
            }
            lv++;
        }
        return -1;
    }
};

 huge perf improve from 1000+ ms to 300 ms: 

use 2-d bool vector<vector<bool>> to replace unordered_set
class Element {
public:
    int x, y, h;
    Element(int x, int y, int h) {
        this->x = x;
        this->y = y;
        this->h = h;
    }
};
class Solution {
public:
    int m;
    int n;
    int cutOffTree(vector<vector<int>>& forest) {
        m = forest.size();  if (m == 0) return 0;
        n = forest[0].size();   if (n == 0) return 0;
        vector<Element> v;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if (forest[i][j] > 1)
                    v.emplace_back(i, j, forest[i][j]);
        auto comp = [](const Element& a, const Element& b) { return a.h < b.h; };
        v.emplace_back(0, 0, 0);
        sort(v.begin(), v.end(), comp);
        
        int res = 0;
        for (int i = 0; i < v.size()  - 1; i++) {
            int t = helper(forest, v[i], v[i+1]);
            if (t < 0)  return t;
            res += t;
        }
        return res;
    }
    int helper(vector<vector<int>>& forest, const Element& a, const Element& b) {
        const int dirs[] = { -1, 0, 1, 0, -1 };
        // (x,y) is small enough, so x*n+y won't overflow. otherwise we have to use long,
        // and be careful x*n+y will overflow, we may use (long)x*n+y instead.
        vector<vector<bool>> s(m, vector<bool>(n));
        queue<pair<int,int>> q;
        q.emplace(a.x, a.y);
        s[a.x][a.y] = true;
        int lv = 0;
        while (!q.empty()) {
            int qsz = q.size();
            for (int i = 0; i < qsz; i++) {
                auto cur = q.front();
                q.pop();
                if (cur.first == b.x && cur.second == b.y)
                    return lv;
                for (int i = 0; i < 4; i++) {
                    int nx = cur.first + dirs[i];
                    int ny = cur.second + dirs[i+1];
                    pair<int,int> np = {nx,ny};
                    if (nx >= 0 && nx < m && ny >= 0 && ny < n && 
                        forest[nx][ny] > 0 &&
                        !s[nx][ny]) {
                        q.push(np);
                        s[nx][ny] = true;
                    }
                }
            }
            lv++;
        }
        return -1;
    }
};

 

posted @ 2018-11-29 23:39  JTechRoad  阅读(116)  评论(0编辑  收藏  举报