Java實現 LeetCode 749 隔離病毒(DFS嵌套)

749. 隔離病毒

病毒擴散得很快,如今你的任務是儘量地經過安裝防火牆來隔離病毒。java

假設世界由二維矩陣組成,0 表示該區域未感染病毒,而 1 表示該區域已感染病毒。能夠在任意 2 個四方向相鄰單元之間的共享邊界上安裝一個防火牆(而且只有一個防火牆)。ide

天天晚上,病毒會從被感染區域向相鄰未感染區域擴散,除非被防火牆隔離。現因爲資源有限,天天你只能安裝一系列防火牆來隔離其中一個被病毒感染的區域(一個區域或連續的一片區域),且該感染區域對未感染區域的威脅最大且保證惟一。spa

你須要努力使得最後有部分區域不被病毒感染,若是能夠成功,那麼返回須要使用的防火牆個數; 若是沒法實現,則返回在世界被病毒所有感染時已安裝的防火牆個數。code

示例 1:

輸入: 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]]
輸出: 10
說明:
一共有兩塊被病毒感染的區域: 從左往右第一塊須要 5 個防火牆,同時若該區域不隔離,晚上將感染 5 個未感染區域(即被威脅的未感染區域個數爲 5;
第二塊須要 4 個防火牆,同理被威脅的未感染區域個數是 4。所以,第一天先隔離左邊的感染區域,通過一晚後,病毒傳播後世界以下:
[[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]]
第二題,只剩下一塊未隔離的被感染的連續區域,此時須要安裝 5 個防火牆,且安裝完畢後病毒隔離任務完成。
示例 2:

輸入: grid = 
[[1,1,1],
 [1,0,1],
 [1,1,1]]
輸出: 4
說明: 
此時只須要安裝 4 面防火牆,就有一小區域能夠倖存,不被病毒感染。
注意不須要在世界邊界創建防火牆。
示例 3:

輸入: 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]]
輸出: 13
說明: 
在隔離右邊感染區域後,隔離左邊病毒區域只須要 2 個防火牆了。

說明:資源

grid 的行數和列數範圍是 [1, 50]。
grid[i][j] 只包含 0 或 1 。
題目保證每次選取感染區域進行隔離時,必定存在惟一一個對未感染區域的威脅最大的區域。it

class Solution {
     int n, m;
    boolean[][] visited;
    Set<Integer> set = new TreeSet<>();
    public int containVirus(int[][] grid) {
        int res = 0;
        n = grid.length;
        m = grid[0].length;
        while (true){
            visited = new boolean[n][m];
            PriorityQueue<int[]> q = new PriorityQueue<>(((o1, o2) -> o2[0]-o1[0]));
            for (int i = 0; i < n; i++){
                for (int j = 0; j < m; j++){
                    if (!visited[i][j] && grid[i][j] == 1){
                        set.clear();
                        int barriers = dfs(grid, i, j);
                        int infected = set.size();
                        q.offer(new int[]{infected, barriers, index(i, j)});
                    }
                }
            }
            if (q.size() == 0){
                break;
            }
            int[] t = q.poll();
            res += t[1];
            dfs1(grid, t[2] / m, t[2] % m);
            for (int i = 0; i < n; i++){
                Arrays.fill(visited[i], false);
            }
            for (int i = 0; i < n; i++){
                for (int j = 0; j < m; j++){
                    if (!visited[i][j] && grid[i][j] == 1){
                        dfs2(grid, i, j);
                    }
                }
            }

        }
        return res;
    }

    private void dfs2(int[][] grid, int i, int j) {
        if (grid[i][j] == 2){
            return;
        }
        visited[i][j] = true;
        if (i - 1 >= 0 && !visited[i - 1][j]){
            if (grid[i - 1][j] == 0){
                grid[i - 1][j] = 1;
                visited[i - 1][j] = true;
            }else{
                dfs2(grid, i - 1, j);
            }
        }
        if (i + 1 < n && !visited[i + 1][j]){
            if (grid[i + 1][j] == 0){
                grid[i + 1][j] = 1;
                visited[i + 1][j] = true;
            }else{
                dfs2(grid, i + 1, j);
            }
        }
        if (j - 1 >= 0 && !visited[i][j - 1]){
            if (grid[i][j - 1] == 0){
                grid[i][j - 1] = 1;
                visited[i][j - 1] = true;
            }else{
                dfs2(grid, i, j - 1);
            }
        }
        if (j + 1 < m && !visited[i][j + 1]){
            if (grid[i][j + 1] == 0){
                grid[i][j + 1] = 1;
                visited[i][j + 1] = true;
            }else{
                dfs2(grid, i, j + 1);
            }
        }
    }

    private void dfs1(int[][] grid, int i, int j) {
        grid[i][j] = 2;
        if (i - 1 >= 0){
            if (grid[i - 1][j] == 1){
                dfs1(grid, i - 1, j);
            }
        }
        if (i + 1 < n){
            if (grid[i + 1][j] == 1){
                dfs1(grid, i + 1, j);
            }
        }
        if (j - 1 >= 0){
            if (grid[i][j - 1] == 1){
                dfs1(grid, i, j - 1);
            }
        }
        if (j + 1 < m){
            if (grid[i][j + 1] == 1){
                dfs1(grid, i, j + 1);
            }
        }
    }


    private int dfs(int[][] grid, int i, int j) {
        if (grid[i][j] == 2){
            return 0;
        }
        visited[i][j] = true;
        int cur = 0;
        if (i - 1 >= 0 && !visited[i - 1][j]){
            if (grid[i - 1][j] == 0){
                cur++;
                set.add(index(i - 1, j));
            }else{
                cur += dfs(grid, i - 1, j);
            }
        }
        if (i + 1 < n && !visited[i + 1][j]){
            if (grid[i + 1][j] == 0){
                cur++;
                set.add(index(i + 1 ,j));
            }else{
                cur += dfs(grid, i + 1, j);
            }
        }
        if (j - 1 >= 0 && !visited[i][j - 1]){
            if (grid[i][j - 1] == 0){
                cur++;
                set.add(index(i, j - 1));
            }else{
                cur += dfs(grid, i, j - 1);
            }
        }
        if (j + 1 < m && !visited[i][j + 1]){
            if (grid[i][j + 1] == 0){
                cur++;
                set.add(index(i, j + 1));
            }else{
                cur += dfs(grid, i, j + 1);
            }
        }
        return cur;
    }

    private int index(int i, int j){
        return m * i + j;
    }
}
相關文章
相關標籤/搜索