我查看了很多类似于这个问题的论坛代码,但我仍然无法解决我的问题。基本上,给定一个大小为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;
}
}
}
提前致谢!!
答案 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;的坐标。 (或者更确切地说,输入中的非整数)。它基于你的,有这些笔记:
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;
}
}