通过2D数组找到FIXED长度的路径,该数组给出最大总和

时间:2014-10-24 10:33:39

标签: java recursion path multidimensional-array maze

我查看了很多类似于这个问题的论坛代码,但我仍然无法解决我的问题。基本上,给定一个大小为n的二维正方形数组,在[-100,100]内填充整数,我必须找到最大总和,假设路径长度为10.这是从某个给定网格开始完成的(用*表示) )。两次访问同一网格是违法的。

示例测试用例是:

-55  34 -51  35  1
-76  26  69  61  *
 68  98  17  85  81
-27 -69  49  42  83
-10  31  44  75 -41

会产生637的最大总和。 由路径表示:61 69 26 98 17 85 81 83 42 75

如果我没错,我代码的问题在于标记我之前访问过的网格。但我不知道如何解决这个问题。

以下是我的代码:

import java.util.*;

class Maze
{
static int[][] matrix;
static int counter = 0;
static int size = 0;
static int maximum = -100000;
static int result = -1000000;
static int currMax; 
static int topMax, downMax, leftMax, rightMax;

public static void main(String [] args)
{
    Scanner sc = new Scanner(System.in);
    size = sc.nextInt();
    matrix = new int[size][size];
    int xcord = 0;
    int ycord = 0;
    for (int i=0; i<size; i++){
        for (int j=0; j<size; j++){
            if (sc.hasNextInt()){
                int util = sc.nextInt();
                matrix[i][j] = util;
            }
            else{
                String utilStr = sc.next();
                xcord = i;
                ycord = j;
                matrix[i][j] = -2000;
            }
        }
    }
    result = 2000 + findMax(xcord, ycord);
    System.out.println(result);
}

static int findMax(int currx, int curry){
    if (counter >= 9){
            return matrix[currx][curry];
    }
    else {
        counter = counter+1;

        System.out.println("Round: "+counter);
        System.out.println("currx: "+currx+" curry: "+curry);
        int temp = matrix[currx][curry];
        matrix[currx][curry] = -2000;

        downMax = -10000; //To reset it for comparison
        if (currx+1 != size && matrix[currx+1][curry] == -2000){
        downMax = findMax(currx+1,curry);
        }
        rightMax = -10000;
        if (curry+1 != size && matrix[currx][curry+1] == -2000){
        rightMax =  findMax(currx,curry+1);
        }
        topMax = -10000;
        if (currx-1 >=0 && matrix[currx-1][curry] == -2000){
        topMax =  findMax(currx-1,curry);
        }
        leftMax = -10000;
        if (curry-1 >= 0 && matrix[currx][curry-1] == -2000){
        leftMax =  findMax(currx,curry-1);
        }

        matrix[currx][curry] = temp;

        currMax = Math.max(downMax,rightMax);
        currMax = Math.max(currMax, topMax);
        currMax = Math.max(currMax, leftMax);

        maximum = currMax + temp;
        return maximum;
        }
}

}

提前致谢!!

2 个答案:

答案 0 :(得分:2)

以下是我的解决方案和解释:

public static int MAX_DEPTH = 10;

static Integer[][] matrix;
static Coord[] directions = {
    new Coord(-1, 0),
    new Coord(1, 0),
    new Coord(0, -1),
    new Coord(0, 1)
};

private static class Coord {
    int row;
    int col;

    private Coord(int row, int col) {
        this.col = col;
        this.row = row;
    }

    private Coord newPosition(Coord relative) {
        return new Coord(row + relative.row, col + relative.col);
    }
}

首先,我将矩阵定义为Integer而不是int的2D数组。这样可以很容易地标记访问过的位置和&#34; *&#34;使用null的位置。这只是一种便利。

我正在使用一个小的内部类Coord来帮助我进行坐标计算。如您所见,我创建了一个静态数组,其中包含我在每一步都需要探索的所有方向,因为这将简化递归方法,并防止不必要的重复代码,以后可能需要在四个不同位置进行修复。

private static Coord fillMatrix() {
    Scanner sc = new Scanner(System.in);
    int size = sc.nextInt();
    matrix = new Integer[size][size];
    Coord coord = new Coord(0, 0);
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            if (sc.hasNextInt()) {
                int util = sc.nextInt();
                matrix[i][j] = util;
            } else {
                sc.next();
                coord.row = i;
                coord.col = j;
                matrix[i][j] = null;
            }
        }
    }
    sc.close();
    return coord;
}

我的fillMatrix方法填充矩阵并返回&#34; *&#34;的坐标。 (或者更确切地说,输入中的非整数)。它基于你的,有这些笔记:

  • 我标记了&#34; *&#34;放在矩阵中,带有null。
  • 您应关闭所有打开的扫描仪。
  • 没有必要定义一个变量来存储扫描&#34; *&#34;的值,因为我们不会使用它。 Java允许调用返回值的方法,而无需在任何地方分配该值。
    private static boolean isLegalPosition(Coord position) {

        if ( position.row < 0 || position.row >= matrix.length ) {
            return false;
        }

        if ( position.col < 0 || position.col >= matrix[0].length ) {
            return false;
        }

        return matrix[position.row][position.col] != null;
    }

给定矩阵中的位置,此方法检查它是否合法 - 如果它在数组的边界内(我们必须假设至少存在一行),并且如果它没有标记为{{1 (访问/开始)。

现在我们来看看递归方法本身。您将当前深度和当前累计总和传递给它,当然,还应该从它应该开始查看的当前位置传递。假设此位置已标记为空。

null

如您所见,我保留了一个名为 private static Integer findMax(Coord currPosition, int currDepth, int currSum) { // Recursion end: if we reached a depth of 10, we have the maximum at // the current position if (currDepth == MAX_DEPTH) { return currSum; } // Find the greatest number in all four directions. We start with an // unknown Max value. Integer currMax = null; for (Coord direction : directions) { Coord newPos = currPosition.newPosition(direction); // If the position is legal (inside the matrix and not visited), // explore it by adding depth, and adding the current matrix // value to the accumulated. if (isLegalPosition(newPos)) { // Save the value at the new position, and mark it as visited. int matrixValue = matrix[newPos.row][newPos.col]; matrix[newPos.row][newPos.col] = null; Integer newMax = findMax(newPos, currDepth + 1, currSum + matrixValue); // Restore the value in the current matrix position so that // upper level recursions don't think it's visited. matrix[newPos.row][newPos.col] = matrixValue; // Calculate the new max. If this is the first legal path, use // it. Otherwise check which one is greater. if (newMax != null) { currMax = (currMax == null) ? newMax : (newMax > currMax ? newMax : currMax); } } } return currMax; } 的变量,该变量的开头为currMax。它最终将成为从四个方向收集的所有数字中的最大值。但是可能发生的是,所有四个方向都无法达到深度10,因为它们会碰到墙壁并到达位置。在这种情况下,它们将返回null,如果在所有四个方向上发生这种情况,我们也会返回currMax - 这是null

如果我们确实在任何方向找到了合法路径,我们会用它更新null(当然,如果它大于它)。

在每一步,在我们深入了解递归之前,我们用null标记新位置以显示它已被访问,但是一旦我们完成它就要小心地恢复它。否则,该位置将保持标记以便访问下一个方向,因此不应将其视为currMax

填充矩阵后,visited对递归的调用当然是这样的:

main

也就是说,我们传递&#34; *&#34;的坐标,从0的深度开始,累计和为0.为什么0而不是-2000?因为我们实际上并没有比较这个数字。我们经历的实际到达深度10的任何路径将返回它已遍历的位置的实际总和,加到该零,无论该总和是负还是正。任何不在深度10处结束的路径都将返回null。所以不需要人为的价值观。

答案 1 :(得分:0)

这个怎么样?当前搜索路径存储在Stack容器中,这有助于识别我们已经看到的位置。在每个递归级别,我们查看当前位置的字段S / N / W / E,如果当前堆栈大小== 11(开始字段加上其余部分),则将currMax设置为当前总和。

import java.util.*;
import java.io.*;



class Coord {
    public Coord(int i,int j) {
        this.i=i;
        this.j=j;
    }
    public boolean equals(Object o) {
        return ((Coord)o).i == i && ((Coord)o).j == j;
    }

    public int i;
    public int j;
};

class Main {
    static int[][] matrix;
    static int counter = 0;
    static int size = 0;
    static int currMax=-2000; 
    static Stack<Coord> currStack = new Stack<Coord>();


    public static void main(String [] args) throws FileNotFoundException
    {
        FileInputStream f=new FileInputStream(new File("/home/bla/bla.txt"));
        Stack<Coord> s = new Stack<Coord> ();

        Scanner sc = new Scanner(f);
        size = sc.nextInt();

        matrix = new int[size][size];
        int xcord = 0;
        int ycord = 0;
        for (int i=0; i<size; i++){
            for (int j=0; j<size; j++){
                if (sc.hasNextInt()){
                    int util = sc.nextInt();
                    matrix[i][j] = util;
                }
                else{
                    String utilStr = sc.next();
                    s.push(new Coord(i,j));
                }
            }
        }

        int sum=0;
        System.out.println(findMax(s,sum));

        Iterator<Coord> i=currStack.iterator();
        int ss=0;
        while(i.hasNext()) {
            Coord c = i.next();
            System.out.println(c.i+" "+c.j+" "+matrix[c.i][c.j]);
            ss+=matrix[c.i][c.j];

        }
        System.out.println("<"+ss+">");

    }

    static int findMax(Stack<Coord> s,int sum){

        // TOP
        if(s.lastElement().i > 0    && (s.search(new Coord(s.lastElement().i-1,s.lastElement().j  ))==-1) ) {
            Stack<Coord> nstack = (Stack<Coord>)s.clone();
            nstack.push(new Coord(s.lastElement().i-1,s.lastElement().j  ));
            int nsum = sum + matrix[nstack.lastElement().i][nstack.lastElement().j];
            if(nstack.size()<11) {
                nsum=findMax(nstack,nsum);
            }
            else {
                if(nsum > currMax) {
                    currMax   = nsum;
                    currStack = nstack;
                }
            }
        }
        // BOTTOM
        if(s.lastElement().i+1 < matrix.length && (s.search(new Coord(s.lastElement().i+1,s.lastElement().j  ))==-1) ) {
            Stack<Coord> nstack = (Stack<Coord>)s.clone();
            nstack.push(new Coord(s.lastElement().i+1,s.lastElement().j  ));            
            int nsum = sum + matrix[nstack.lastElement().i][nstack.lastElement().j];
            if(nstack.size()<11) {
                nsum = findMax(nstack,nsum);
            }
            else {
                if(nsum>currMax) {
                    currMax   = nsum;
                    currStack = nstack;
                }
            }
        }
        // LEFT
        if(s.lastElement().j > 0   && (s.search(new Coord(s.lastElement().i  ,s.lastElement().j-1))==-1) ) {
            Stack<Coord> nstack = (Stack<Coord>)s.clone();
            nstack.push(new Coord(s.lastElement().i  ,s.lastElement().j-1));
            int nsum = sum + matrix[nstack.lastElement().i][nstack.lastElement().j];
            if(nstack.size()<11) {
                nsum = findMax(nstack,nsum);
            }
            else {
                if(nsum>currMax) {
                    currMax   = nsum;
                    currStack = nstack;
                }
            }
        }

        // RIGHT
        if(s.lastElement().j+1 < matrix[0].length && (s.search(new Coord(s.lastElement().i  ,s.lastElement().j+1))==-1) ) {
            Stack<Coord> nstack = (Stack<Coord>)s.clone();
            nstack.push(new Coord(s.lastElement().i  ,s.lastElement().j+1));
            int nsum = sum +matrix[nstack.lastElement().i][nstack.lastElement().j];
            if(nstack.size()<11) {
                nsum = findMax(nstack,nsum);
            }
            else {
                if(nsum>currMax) {
                    currMax   = nsum;
                    currStack = nstack;
                }
            }
        }
        return currMax;
    }
}