LeetCode "Shortest Distance from All Buildings"

Nothing magic here. Just BFS, but - BFS from land is not a good idea - BFS from Buildings.

Lesson learnt: reverse thinking helps!

class Solution {
public:
    int shortestDistance(vector<vector<int>>& grid)     
    {
         int ret = 0;
        
        //    Get dimension
        int h = grid.size();        if(!h) return ret;        
        int w = grid[0].size();        if(!w) return ret;
        
        //    Get all buildings
        typedef pair<int, int> Loc;
        vector<Loc> buildings;
        for(int i = 0; i < h; i ++)
        for(int j = 0; j < w; j ++)
        {
            if(grid[i][j] == 1)
            {
                buildings.push_back(Loc(i, j));
            }
        }
        
        size_t n = buildings.size();
        unsigned long long FullMask = ((unsigned long long)1 << n) - 1;
        
        //
        struct Rec
        {
            unsigned long long mask;
            int ttl;
        };        
        
        ret = INT_MAX;
        vector<vector<Rec>> inf(h, vector<Rec>(w));
        for(int i = 0; i < buildings.size(); i ++)
        {
            Loc &b = buildings[i];
            
            queue<Loc> q;
            vector<vector<bool>> visited(h, vector<bool>(w, false));        
            vector<vector<bool>> inq(h, vector<bool>(w, false));    
            q.push(b); visited[b.first][b.second] = inq[b.first][b.second] = true;
            
            int layerCnt = 1, layer = 0;
            while(!q.empty())
            {
                Loc c = q.front(); q.pop();
                visited[c.first][c.second] = true;
                
                // Mark
                if(grid[c.first][c.second] == 0)
                {
                    inf[c.first][c.second].mask |= (unsigned long long)1 << i;
                    inf[c.first][c.second].ttl  += layer;
                    if(i == (buildings.size() - 1))
                    {
                        if(inf[c.first][c.second].mask == FullMask)
                            ret = min(ret, inf[c.first][c.second].ttl);
                    }
                }                
                
                int dx[] = {-1,  0, 1, 0};
                int dy[] = { 0, -1, 0, 1};
                for(int k = 0; k < 4; k ++)
                {
                    Loc nc(c.first + dy[k], c.second + dx[k]);
                    if((nc.first >= 0 && nc.first < h && nc.second >= 0 && nc.second < w) 
                        && (!grid[nc.first][nc.second] && !visited[nc.first][nc.second] &&
                        (!inq[nc.first][nc.second]))
                    )
                    {
                        q.push(nc);
                        inq[nc.first][nc.second] = true;
                    }
                }
                
                layerCnt --;
                if(!layerCnt)
                {
                    layerCnt = q.size();
                    layer ++;
                }
            }
        }
        
        return ret == INT_MAX? -1 : ret;
    }
};
View Code

Yes there are several optimizations feasible above.

你可能感兴趣的:(LeetCode "Shortest Distance from All Buildings")