如何计算网格中连接的单元格?

时间:2016-09-18 20:27:26

标签: c++ matrix

我试图解决Hackerrank问题"Connected Cells in a Grid"。任务是找到网格中最大的区域(连接的单元格由1组成)。

我的方法是添加我找到的数量,只有在尚未访问该元素的情况下,然后我才采用最多的几个路径。它似乎不适用于以下测试用例:

5
5
1 1 0 0 0
0 1 1 0 0
0 0 1 0 1
1 0 0 0 1
0 1 0 1 1

我的方法有问题吗?

#include <vector>
#include <algorithm>
using namespace std;

#define MAX 10
bool visited[MAX][MAX];

int maxRegion(vector<vector<int>> const& mat, int i, int j) { 
  int result;

  if ((i == 0 && j == 0) || visited[i][j]) {
    result = 0;
  }
  else if (i == 0) {
      result = mat[i][j-1] + maxRegion(mat, i, j-1);
  }
  else if (j == 0) {
      result = mat[i-1][j] + maxRegion(mat, i-1, j);
  }
  else {
    result = mat[i-1][j-1] +
      max({maxRegion(mat, i-1, j),
           maxRegion(mat, i, j-1),
           maxRegion(mat, i-1, j-1)});
  }
  visited[i][j] = true;
  return result;
}

3 个答案:

答案 0 :(得分:1)

我认为将此程序表述为connected components问题是很自然的。具体来说,我已经使用了boost::graph

这个想法是建立一个图表,其矩阵中的每个条目都是一个节点,水平和垂直1个条目之间有边。构建这样的图之后,所需要的只是运行连通组件算法,并找到最大的组件。

以下代码执行此操作:

#include <iostream>
#include <vector>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/connected_components.hpp>

using namespace std;
using namespace boost;

int main()
{   
    vector<vector<int>> v{{1, 1, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 0, 1}, {1, 0, 0, 0, 1}, {0, 1, 0, 1, 1}};

    typedef adjacency_list <vecS, vecS, undirectedS> graph;

    graph g(v.size() * v.size());

    // Populate the graph edges
    for(size_t i = 0; i < v.size() - 1; ++i)
        for(size_t j = 0; j < v[i].size() - 1; ++j)
        {
            if(v[i][j] == 1 && v[i + 1][j] == 1)
                add_edge(i * v.size() + j, (i + 1) * v.size() + j, g);
            else if(v[i][j] == 1 && v[i][j + 1] == 1)
                add_edge(i * v.size() + j, i * v.size() + j + 1, g);
        }

     // Run the connected-components algorithm.
     vector<int> component(num_vertices(g));
     int num = connected_components(g, &component[0]);

     // Print out the results.
     std::vector<int>::size_type i;
     for(i = 0; i != component.size(); ++i)
         cout << "Vertex (" << i / v.size() << ", " << i % v.size()  << ") is in component " << component[i] << endl;
     cout << endl;
}

输出

Vertex (0, 0) is in component 0
Vertex (0, 1) is in component 0
Vertex (0, 2) is in component 1
Vertex (0, 3) is in component 2
Vertex (0, 4) is in component 3
Vertex (1, 0) is in component 4
Vertex (1, 1) is in component 0
Vertex (1, 2) is in component 0
Vertex (1, 3) is in component 5
Vertex (1, 4) is in component 6
Vertex (2, 0) is in component 7
Vertex (2, 1) is in component 8
Vertex (2, 2) is in component 0
Vertex (2, 3) is in component 9
Vertex (2, 4) is in component 10
Vertex (3, 0) is in component 11
Vertex (3, 1) is in component 12
Vertex (3, 2) is in component 13
Vertex (3, 3) is in component 14
Vertex (3, 4) is in component 15
Vertex (4, 0) is in component 16
Vertex (4, 1) is in component 17
Vertex (4, 2) is in component 18
Vertex (4, 3) is in component 19
Vertex (4, 4) is in component 20

请注意,程序通过 5 i + j i,j (对于维度为5的情况)进行编码。这很容易逆转。

答案 1 :(得分:0)

您可以将矩阵表示为无向图,并使用DFSBFS查找节点数最多的connected component:每个包含1的单元格都可以成为< em> node ,如果相应的单元格相邻,则两个节点之间存在 edge

答案 2 :(得分:0)

如果您仍需要解决方案的一些指导,here is mine in Python - 通过所有测试:)(访问我的github以查看我在C ++中解决的其他挑战)< / p>

def getBiggestRegion(grid, n, m):
    max_region = 0
    region_size = 0
    for i in xrange(n):
        for j in xrange(m):
            if grid[i][j] == 1:
                region_size = mark_region(grid, i, j, n, m)
                #region_size += 1
                if region_size > max_region:
                    max_region = region_size
    return max_region


def push_if_valid(stack, i, j, n, m):
    if 0 <= i < n and 0 <= j < m:
        stack.append((i, j))

dirs = [[1,0], [0,1], [-1,0], [0,-1], [-1,-1], [-1, 1], [1,1], [1, -1]]
def mark_region(grid, i, j, n, m):
    stack = []
    stack.append((i, j))
    region_size = 0
    while stack:
        curr = stack.pop()
        ci = curr[0]
        cj = curr[1]
        if grid[ci][cj] == 1:
            grid[ci][cj] = 2
            region_size += 1
            #this for loop is for going in all the directions 
            #North, South, East, West, NW, SW, SE, NE
            #in my C++ Pacman sol, I have the actual lines instead
            for dir in dirs:
                push_if_valid(stack, ci + dir[0], cj + dir[1], n, m)

    return region_size

n = int(raw_input().strip())
m = int(raw_input().strip())
grid = []
for grid_i in xrange(n):
    grid_t = list(map(int, raw_input().strip().split(' ')))
    grid.append(grid_t)
print(getBiggestRegion(grid, n, m))