在2d阵列中查找连接的单元

时间:2014-02-12 01:39:32

标签: java arrays

修改:已解决,请参阅下面的帖子。

我正在用Java实现棋盘游戏,需要开发一种算法来查找2d阵列中单个单元的“连接”单元数。

编辑:通过连接,我的意思是与我正在开始的单元格具有相同的值。如果方法调用值为x的单元格,我需要找到与它共享边缘的所有那些(不是对角线)。

IE如果我有这个2d的1和0数组,我想找到我选择的单个单元格中最多的连接单元格:

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

在[0] [0]上运行算法将返回10,因为有6个1连接在右侧路径上,3个在左侧路径上连接。

有没有一种已知的方法可以解决这个问题?如果没有,你会如何解决它?我绞尽脑汁似乎无法找到方法。任何建议表示赞赏。

4 个答案:

答案 0 :(得分:2)

您可能需要查看一些路径查找算法。

最常见也是最快的是Dijkstra's Algorithm

这个概念很容易理解和实施。找到一条路径,你可以找到你正在搜索的区域周围1或0的连接。

在Java中查看使用Dijkstra算法对2D阵列进行路径查找。 Path Finding

通过查看环绕声“节点”(1或0),您可以找到“连接”部分。

答案 1 :(得分:1)

解决了,这就是我所做的:

// Java the board game: find connected spaces

public class findConnectedCells
{
    public static int findNumberConnected(int a, int b, int[][] z)
    {
        boolean canUp = (a - 1 >= 0);
        boolean canDown = (a + 1 < z.length);
        boolean canRight = (b + 1 < z[0].length);
        boolean canLeft = (b - 1 >= 0);

        int value = z[a][b];

        int up = 0;
        int down = 0;
        int right = 0;
        int left = 0;

        z[a][b] = 2;

        if (canUp && z[a-1][b] == value)
        {
            up = findNumberConnected(a-1,b,z);
        }
        if (canDown && z[a+1][b] == value)
        {
            down = findNumberConnected(a+1,b,z);
        }
        if (canLeft && z[a][b-1] == value)
        {
            left = findNumberConnected(a,b-1,z);
        }
        if (canRight && z[a][b+1] == value)
        {
            right = findNumberConnected(a,b+1,z);
        }

        return up + left + right + down + 1;
    }


    public static void main(String[] args) {
        System.out.println("Finding connections");

        int[][] z = new int[][]{

                      { 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1 },
                      { 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1 },
                      { 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1 },
                      { 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1 },
                      { 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1 },   
                    };
        int x = 0;
        int y = 0;

        System.out.println("Number of connected cells from "+x+","+y+" is: "+findNumberConnected(x,y,z));
    }
}

答案 2 :(得分:0)

检查深度优先搜索。递归算法的想法如下:

  1. 创建空的单元格堆。

  2. 添加到堆栈起始位置(例如0,0)。

  3. 拉出堆叠中的单元格(这意味着 - 将其从堆栈中移除并准备探索它)并探索此单元格具有的相邻单元格,添加符合您条件的所有相邻单元格(== 1并共享边缘)到同一堆栈。 Mark看到拉出细胞。

  4. 重复#3,直到你的桌子上看不见的单元格,或者你面对的是一组相邻的单元格,这些单元格没有任何符合你条件的单元格或者堆栈变空。

  5. 你应该以某种方式记住你传递的方式并选择最长的一个(包含更多的1)

    这是一个非常简单和简短的算法。 祝你好运!

答案 3 :(得分:0)

深度优先搜索是关键算法和更好的解决方法,因为如果数组在每个维度中都是大数字,那么您将得到 StackOverFlow异常。首先,将细胞连接到过去,如下所示;左上,上,右上和左上。这将涵盖所有可能的联系。

_ _ _
_ x

然后,一旦有效连接单元格,只需在所有矩阵中进行深度优先遍历。当您在该区域时,继续增加区域计数,就像您进行深度优先遍历一样,直到您再次找到未访问的节点并执行相同操作。如果新区域计数较大,则将其替换为最大区域计数。

以下是实施

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
import java.util.stream.Stream;

public class SolutionNoRecursion {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);        
        int row = Integer.valueOf(in.nextLine());
        Node[][] matrix = new Node[row][Integer.valueOf(in.nextLine())];

        int count = 0;

        LinkedList<Node> nodes = new LinkedList<>();

        while(row-->0){            
            int[] numbers = Stream.of(in.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();

            for (int column = 0; column < numbers.length; column++) {
                if(numbers[column] == 1){                    
                    Node node = new Node();
                    nodes.add(node);
                    matrix[count][column] = node;
                    if(count > 0 && count <= matrix.length){
                        Node upperNode = matrix[count-1][column];
                        connectNodesToEachOther(node, upperNode);
                        if(column < numbers.length-1){
                            Node upperRightNode = matrix[count-1][column+1];
                            connectNodesToEachOther(node, upperRightNode);
                        }
                    }

                    if(column > 0){
                        Node leftNode = matrix[count][column-1];
                        connectNodesToEachOther(node, leftNode);
                    }

                    if(column>0 && count>0){
                        Node upperLeftNode = matrix[count-1][column-1];
                        connectNodesToEachOther(node, upperLeftNode);
                    }                                        
                }                
            }
            count++;
        }
        in.close();


        int maxSoFar = 0;
        for (Node node : nodes) {
            if(node.visited){
                continue;
            }
            node.visited = true;
            int regionCount = 1;
            Stack<Node> stack = new Stack<>();
            stack.push(node);
            while(!stack.empty()){
                Node connection = stack.pop();
                if(!connection.visited){
                    connection.visited = true;
                    regionCount++;
                }
                for(Node nodeCon : connection.connections){
                    if(!nodeCon.visited){
                        stack.push(nodeCon);                        
                    }
                }
            }
            maxSoFar = regionCount > maxSoFar ? regionCount : maxSoFar;
        }

        System.out.println(maxSoFar);
    }

    protected static void connectNodesToEachOther(Node node, Node upperNode) {
        if(upperNode != null){
            node.connections.add(upperNode);
            upperNode.connections.add(node);
        }
    }

}

class Node{
    boolean visited = false;
    List<Node> connections = new LinkedList<>();
}