如何在矩阵中找到A到任何B的最近路径?

时间:2012-06-22 13:05:45

标签: java path shortest

例如:

m_array = new int[6][6];
m_array[0] = new int[]{2, 0, 0, 0, 0, 0};
m_array[1] = new int[]{0, 2, 0, 0, 0, 2};
m_array[2] = new int[]{2, 0, 0, 1, 0, 0};
m_array[3] = new int[]{0, 0, 0, 0, 0, 0};
m_array[4] = new int[]{0, 2, 0, 0, 2, 0};
m_array[5] = new int[]{0, 0, 2, 0, 0, 0};

如何找到最接近的2对1?

我想要一个函数,它返回一个包含数组点的数组路径。例如,我将“m_array”赋予我的函数,它将返回给我最接近的2为1,数组路径如[2,3] [3,4] [4,4]

5 个答案:

答案 0 :(得分:1)

这些是你让我们猜测的事情:

  • 只有一个1,但很多2个;
  • 路径允许对角线步骤;
  • 您正在寻找将1连接到2的所有路径中最短的路径。

我目前的想法是,可以为任意两点之间的路径长度定义一个度量,因此概念“a 2的最短路径为1”等同于“2最接近1的概念” ”。度量可以定义为中心1周围的“环”数必须交叉以达到2:

0 0 0
0 1 0
0 0 2  --> the 2 is in the first ring

0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 2 0 0 0 --> the 2 is in the second ring.

如果我的所有假设都是正确的,那么你需要一个函数给出第一个环的所有成员,第二个环,依此类推,另外一个函数将搜索一个2的环。然后,最后,你需要一个算法来绘制路径2.我希望你意识到路径不是唯一的。一个简单的算法将沿对角线移动,直到与2对齐(水平或垂直),然后继续非对角线到目标。

答案 1 :(得分:0)

不确定你的意思,因为你似乎在问两件不同的事情。我不能在路径方面提供帮助,因为你没有详细说明我们如何移动。 你似乎也在问如何找到最接近的2比1.尽管不是最有效的,你可以简单地遍历矩阵并使用毕达哥拉斯根据指数计算出每个2比1的距离。或者,您可以从1开始,以方形形状从1开始遍历矩阵。这可能会更快,因为您将停止第二次找到2,而不是必须使用第一个解决方案遍历整个矩阵检查2s,尽管第一个解决方案更容易实现,并且不应该产生那么大的差异,因为你的矩阵很小(我相信两者都是O(n),但第二种方法最好的情况是你可以在第一次检查中找到2,而在使用毕达哥拉斯时你总是需要遍历整个矩阵。)

我希望这是有道理的。

在某些澄清之后编辑: 这是一种我希望满足您要求的方法。首先是一个包含点的类,以便于访问。

public class Point {
    private int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() { return x; }
    public int getY() { return y; }
    public int setX(int x) { this.x = x; }
    public int setY(int y) { this.y = y; }

}

现在方法本身:

public ArrayList<Point> getPath(int[][] matrix) {
    Point closestTwo = getClosestTwo(matrix); // Implement this as you wish
    Point onePosition = getOnePosition(matrix);

    ArrayList<Point> pointList = new ArrayList<Point>();

    Point currentlyOn = onePosition;

    while (currentlyOn.getX() != closestTwo.getX() && currentlyOn.getY() != closestTwo.getY()) {
        currentlyOn = oneStep(currentlyOn, closestTwo);
        pointList.add(currentlyOn);
    }

    return pointList;
}

以下是oneStep方法的示例,您可以使用它来更接近。它会返回一个点,这个点可以提升你最多,而只做一步(对角线优先)。

public Point oneStep(Point from, Point goal) {
    int x = from.getX() - goal.getX();
    int y = from.getY() - goal.getY();
    Point nextStep = new Point (from.getX(), from.getY());

    if (x > 0) {
        nextStep.setX(nextStep.getX() + 1)
    } else if (x < 0) {
        nextStep.setX(nextStep.getX() - 1)
    }

    if (y > 0) {
        nextStep.setY(nextStep.getY() + 1)
    } else if (y < 0) {
        nextStep.setY(nextStep.getY() - 1)
    }

    return nextStep;
}

我相信这应该可行。如果你使用它,你应该得到一个PointList。 getClosestTwo方法的一个例子可能是这样的(使用Pythagoras')。记得导入java.lang.Math;

public Point getClosestTwo(int[][] matrix) { // Assumes matrix is initialized, non-empty etc.
    int x, y;
    double smallestDistance = matrix.size() * matrix[0].size(); // bigger than possible
    Point onePosition = getOnePosition(matrix);

    for (int i = 0; i < matrix.size(); i++) {
        for (int j = 0; j < matrix[0].size(); j++) {
            double tmp = (double)(Math.abs(i - y) + Math.abs(j - x))
            double distance = Math.sqrt(tmp);
            if (distance < smallestDistance) {
                y = i;
                x = j;
                smallestDistance = distance;
            }
        }
    }

    return new Point(x, y);
}

getOnePosition(int [] [] matrix)可以简单地实现:

// Return null if no 1 in matrix
public Point getOnePosition(int[][] matrix) {
    for (int i = 0; i < matrix.size(); i++) {
        for (int j = 0; j < matrix[0].size(); j++) {
            if (matrix[i][j] == 1) {
                return new Point(j, i);
            }
        }
    }
    return null;
}

希望这有帮助。记得要检查空值,写安全代码等等。你可以把它们放在一起。我希望此代码没有任何拼写错误或错误,您将无法修复。

答案 2 :(得分:0)

此函数将我的矩阵数组拼接为环半径。

public static int[][] SpliceMatrix(int orginX, int orginY, int ringRadius, int[][] map){

    int[][] tempMap = new int[ringRadius * 2 + 1][ringRadius * 2 + 1];

    int tempY = -ringRadius;
    for(int i = 0; i < (ringRadius * 2 + 1); i++){
        int tempX = -ringRadius;

        for(int j = 0; j < (ringRadius * 2 + 1); j++){
            try{
                tempMap[i][j] = map[orginY + tempY][orginX + tempX];
            }catch(ArrayIndexOutOfBoundsException e){
                tempMap[i][j] = 1;
            }

            tempX++;
        }

        tempY++;
    }

    return tempMap;
}

我在这个函数中使用了A *算法:

private static Point findNext2(int orginX, int orginY, int[][] map){

    //Find "2"s
    ArrayList<Point> ends = new ArrayList<Point>();

    for(int i = 0; i < map.length; i++){
        for(int j = 0; j < map[0].length; j++){
            if(map[i][j] == 2){
                ends.add(new Point(j, i));

                map[i][j] = 0;//Clear for A*
            }
        }
    }

    //Find the closest
    if(ends.size() > 0){
        Point p = null;
        int distance = 100;

        for(int i = 0; i < ends.size(); i++){
            int tempDistance = APlus.go(orginX, orginY, ends.get(i).x, ends.get(i).y, map).size();
            System.out.println(tempDistance);
            if(tempDistance != 0 && tempDistance < distance){
                distance = tempDistance;
                p = new Point(ends.get(i).x, ends.get(i).y);
            }

        }

        if(p == null){
            System.out.println("2 is not accesible");

            return null;
        }

        return p;

    }else{
        System.out.println("There is no 2 in ring");

        return null;
    }

}

然后我用

public static void main(String args[]){

    int[][] m_array = new int[6][6];
    m_array[0] = new int[]{1, 1, 0, 0, 2, 0};
    m_array[1] = new int[]{0, 0, 0, 0, 0, 1};
    m_array[2] = new int[]{1, 1, 1, 0, 1, 0};
    m_array[3] = new int[]{1, 0, 1, 0, 1, 0};
    m_array[4] = new int[]{0, 0, 0, 0, 1, 0};
    m_array[5] = new int[]{0, 0, 0, 0, 0, 0};

    int[][] c = SpliceMatrix(2, 2, 2, m_array);//int x, int y, ringRadius, matrix

    Point p = findNext2(3, 3, c);//orginX, orginY, matrix
    System.out.println(p + " is the closest 2");
 }

我希望这是描述性的。我还不能正确使用HTML。

答案 3 :(得分:0)

我更喜欢使用quickgraph来寻找更近的点或路径; 所以,请看这个链接: http://www.codeproject.com/Articles/5603/QuickGraph-A-100-C-graph-library-with-Graphviz-Sup

答案 4 :(得分:0)

这是我的一段代码。似乎比我在这里看到的任何东西都简单,所以决定张贴:

public static boolean isWithinRadius(int[] position, int[] centerPosition, int radius) {

        int xCenterPoint = centerPosition[0];
        int yCenterPoint = centerPosition[1];
        int zCenterPoint = centerPosition[2];


        int xPoint = position[0];
        int yPoint = position[1];
        int zPoint = position[2];

        boolean xMatch = (xPoint - radius <= xCenterPoint) && (xPoint >= xCenterPoint - radius);
        boolean yMatch = (yPoint - radius <= yCenterPoint) && (yPoint >= yCenterPoint - radius);
        boolean zMatch = (zPoint - radius <= zCenterPoint) && (zPoint >= zCenterPoint - radius);


        return xMatch && yMatch && zMatch;

    } // public boolean isWithinRadius (int[], int)

如果位置在centerPosition的半径范围内,则返回true。

  1. centerPosition是指环的中心。 (如果您不需要Z值,只需在要求的任何地方放置0。)
  2. 半径1 ==环1,半径2 = = Ring1&amp;环2.等。您可以扫描半径。尝试以此为基础。如果您感兴趣,我已经编写了一个高级Matrix类,您可以扫描(基于哈希)并在其中查找对象。 我正要编写返回在半径内找到的对象的ArrayList的代码。
  3. 如果您希望仅在特定环内找到对象(而不是半径内的所有对象),请使用以下代码:

    public static boolean isWithinRadiusRing(int[] position, int[] centerPosition, int radius) {
    
    
            int xCenterPoint = centerPosition[0];
            int yCenterPoint = centerPosition[1];
            int zCenterPoint = centerPosition[2];
    
    
            int xPoint = position[0];
            int yPoint = position[1];
            int zPoint = position[2];
    
            boolean xRingMatch = (xPoint - radius == xCenterPoint) || (xPoint == xCenterPoint - radius);
            boolean yRingMatch = (yPoint - radius == yCenterPoint) || (yPoint == yCenterPoint - radius);
            boolean zRingMatch = (zPoint - radius == zCenterPoint) || (zPoint == zCenterPoint - radius);
    
            boolean xRadiusMatch = (xPoint - radius <= xCenterPoint) && (xPoint >= xCenterPoint - radius);
            boolean yRadiusMatch = (yPoint - radius <= yCenterPoint) && (yPoint >= yCenterPoint - radius);
            boolean zRadiusMatch = (zPoint - radius <= zCenterPoint) && (zPoint >= zCenterPoint - radius);
    
            boolean xMatch = xRingMatch && yRadiusMatch && zRadiusMatch;
            boolean yMatch = yRingMatch && xRadiusMatch && zRadiusMatch;
            boolean zMatch = zRingMatch && xRadiusMatch && yRadiusMatch;
    
            /*
                System.out.println("xRingMatch="+xRingMatch+" yRingMatch="+yRingMatch+" zRingMatch="+zRingMatch);
                System.out.println("xRadiusMatch="+xRadiusMatch+" yRadiusMatch="+yRadiusMatch+" zRadiusMatch="+zRadiusMatch);
                System.out.println("xMatch="+xMatch+" yMatch="+yMatch+" zMatch=" +zMatch);
                System.out.println("return=" + (xMatch || yMatch || zMatch));
            */
    
            return xMatch || yMatch || zMatch;
    
        } // public boolean isWithinRadiusRing(int[], int[] , int)
    

    如果给定位置在距离centerPosition的给定半径范围内(半径1 == ring1,半径2 = =环2等),则返回true

    找出两个位置之间的半径距离:

            public static int getDistanceRadius(int[] startPosition, int[] endPosition) {
    
                // The xyz value that streches the most the distance between two positions
                // is the radius value.
                int xDistance = Math.abs(startPosition[0] - endPosition[0]);
                int yDistance = Math.abs(startPosition[1] - endPosition[1]);
                int zDistance = Math.abs(startPosition[2] - endPosition[2]);
    
                int radius = (xDistance > yDistance ? xDistance : yDistance);        
                radius = (radius > zDistance ? radius : zDistance);
    
                return radius;
    
            } // public static int getDistanceRadius(int[], int[])