void DfsBorder(int[,] grid, int row, int col, bool[,] visited, VirusRegion reg)
        {
            int m = grid.GetLength(0);
            int n = grid.GetLength(1);

            visited[row, col] = true;

            foreach (var dir in Dirs)
            {
                int r = row + dir[0];
                int c = col + dir[1];

                if (0 <= r && r < m && 0 <= c && c < n)
                {
                    if (grid[r, c] == 0)
                    {
                        reg.WallCount++;
                        reg.Borders.Add(r * m + c);
                    }

                    if (grid[r, c] == 1 && !visited[r, c])
                    {
                        DfsBorder(grid, r, c, visited, reg);
                    }
                }
            }
        }
        public int ContainVirus(int[,] grid)
        {
            int ret = 0;
            int m   = grid.GetLength(0);
            int n   = grid.GetLength(1);

            while (true)
            {
                // find the virus region with max border
                var maxreg  = new VirusRegion(0, 0);
                var visited = new bool[m, n];
                for (int i = 0; i < m; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        if (grid[i, j] == 1 && !visited[i, j])
                        {
                            var reg = new VirusRegion(i, j);
                            DfsBorder(grid, i, j, visited, reg);

                            if (maxreg.Borders.Count < reg.Borders.Count)
                            {
                                maxreg = reg;
                            }
                        }
                    }
                }

                if (maxreg.Borders.Count == 0)
                {
                    break;
                }

                // create the wall to quarantine this max region
                ret += maxreg.WallCount;
                DfsWall(grid, maxreg.Row, maxreg.Col);

                // infect all border
                var newInfected = new bool[m, n];
                for (int i = 0; i < m; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        if (grid[i, j] == 1 && !newInfected[i, j])
                        {
                            foreach (var dir in Dirs)
                            {
                                int r = i + dir[0];
                                int c = j + dir[1];

                                if (0 <= r && r < m && 0 <= c && c < n && grid[r, c] == 0)
                                {
                                    grid[r, c]        = 1;
                                    newInfected[r, c] = true;
                                }
                            }
                        }
                    }
                }
            }

            return(ret);
        }