leetcode 749. Contain Virus

A virus is spreading rapidly, and your task is to quarantine the infected area by installing walls.

The world is modeled as a 2-D array of cells, where 0 represents uninfected cells, and 1 represents cells contaminated with the virus. A wall (and only one wall) can be installed between any two 4-directionally adjacent cells, on the shared boundary.

Every night, the virus spreads to all neighboring cells in all four directions unless blocked by a wall. Resources are limited. Each day, you can install walls around only one region -- the affected area (continuous block of infected cells) that threatens the most uninfected cells the following night. There will never be a tie.

Can you save the day? If so, what is the number of walls required? If not, and the world becomes fully infected, return the number of walls used.

 

Example 1:

Input: grid = 
[[0,1,0,0,0,0,0,1],
 [0,1,0,0,0,0,0,1],
 [0,0,0,0,0,0,0,1],
 [0,0,0,0,0,0,0,0]]
Output: 10
Explanation:
There are 2 contaminated regions.
On the first day, add 5 walls to quarantine the viral region on the left. The board after the virus spreads is:

[[0,1,0,0,0,0,1,1],
 [0,1,0,0,0,0,1,1],
 [0,0,0,0,0,0,1,1],
 [0,0,0,0,0,0,0,1]]

On the second day, add 5 walls to quarantine the viral region on the right. The virus is fully contained.

 

Example 2:

Input: grid = 
[[1,1,1],
 [1,0,1],
 [1,1,1]]
Output: 4
Explanation: Even though there is only one cell saved, there are 4 walls built.
Notice that walls are only built on the shared boundary of two different cells.

 

Example 3:

Input: grid = 
[[1,1,1,0,0,0,0,0,0],
 [1,0,1,0,1,1,1,1,1],
 [1,1,1,0,0,0,0,0,0]]
Output: 13
Explanation: The region on the left only builds two new walls.

 

Note:

  1. The number of rows and columns of grid will each be in the range [1, 50].
  2. Each grid[i][j] will be either 0 or 1.
  3. Throughout the described process, there is always a contiguous viral region that will infect strictly moreuncontaminated squares in the next round.

请这位同学好好审题。。。。

解题思路:使用union find找连通的病毒块,每一个病毒块将感染的细胞数量和需要建立的防火墙数量是不一样的。所以需要一个unordered_map存储每个病毒块的细胞集合,key为病毒块的根细胞的秩;一个unordered_map存储每个病毒块将感染的细胞集合,,key为病毒块的根细胞的秩;一个unordered_map存储每个病毒块需要建立的防火墙的数量;

根据题意,首先为将感染细胞数量最多的病毒块建立防火墙,不是我理解的需要建立防火墙数目最多的病毒块建立防火墙。。。

class Solution {
public:
    int containVirus(vector>& grid) 
    {
        int rows = grid.size() , cols = grid[0].size() ;
        vector dir = { -1 , 0 , 1 , 0 , -1} ;
        int res = 0 ; int cnt = 0 ;
        
        while(true)
        {
            root = vector(rows * cols , -1) ;
            for(int i = 0 ; i < rows * cols ; i++) root[i] = i ;
            unordered_map> virus , infecteds ;
            unordered_map walls ;
            int non_infs = 0 , mx_infs = 0 , key = -1 ; 
            for(int i = 0 ; i < rows ; ++i)
                for(int j = 0 ; j < cols ; ++j)
                {
                    if(grid[i][j] == 0)
                    {
                        non_infs++ ;
                        continue ;
                    }
                    else if(grid[i][j] == -1) continue ;
                    
                    set new_infs ;
                    int rt = find(i * cols + j) ;
                    
                    for(int k = 0 ; k < 4 ; ++k)
                    {
                        int new_i = i + dir[k] , new_j = j + dir[k + 1] ;
                        if(new_i < 0 || new_i >= rows || new_j < 0 || new_j >= cols) continue ;
                        if(grid[new_i][new_j] == 0) 
                        {
                            new_infs.insert(new_i * cols + new_j) ;
                            continue ;
                        }
                        else if(grid[new_i][new_j] == 1) 
                        {
                            int x = find(new_i * cols + new_j) ;
                            rt = merge(rt , x , virus , infecteds , walls) ;
                        }
                    }
                    
                    virus[rt].insert(i * cols + j) ;
                    infecteds[rt].insert(new_infs.begin() , new_infs.end()) ;
                    walls[rt] += new_infs.size() ;
                    
                    if(infecteds[rt].size() > mx_infs) 
                    {
                        mx_infs = infecteds[rt].size() ;
                        key = rt ;
                    }
                    
                }
            
            if(non_infs == 0 || mx_infs == 0) return res ;
            
            for(auto ele : virus[key]) grid[ele / cols][ele % cols] = -1 ;
            res += walls[key] ;
            infecteds.erase(key) ;
            for(auto ele : infecteds)
            {
                for(auto e : ele.second) grid[e / cols][e % cols] = 1 ;
            }
            cnt++;
        }
        
        return res ;
    }
    
    int find(int i)
    {
        return root[i] == i ? i : find(root[i]) ;
    }
    
    int merge(int i , int j , unordered_map>& virus , unordered_map>& infecteds , unordered_map& walls)
    {
        int x = find(i) , y = find(j) ;
        if(x < y)
        {
            root[y] = x ;
            virus[x].insert(virus[y].begin() , virus[y].end()) ;
            virus.erase(y) ;
            infecteds[x].insert(infecteds[y].begin() , infecteds[y].end()) ;
            infecteds.erase(y) ;
            walls[x] += walls[y] ;
            walls.erase(y) ;
            return x ;
        }
        else if(x > y)
        {
            root[x] = y ;
            virus[y].insert(virus[x].begin() , virus[x].end()) ;
            virus.erase(x) ;
            infecteds[y].insert(infecteds[x].begin() , infecteds[x].end()) ;
            infecteds.erase(x) ;
            walls[y] += walls[x] ;
            walls.erase(x) ;
            return y ;
        }
        return x ;
    }
    
private:
    vector root ;
};

 

你可能感兴趣的:(leetcode,广度优先搜索,并查集/Union,Find)