我在JAVA中有一个问题,无论我多久尝试考虑解决方案,我都无法解决: 有一个矩阵,我需要找到从Mat [0] [0]到矩阵右下角的最短路径,如果其中的数字我只能进入相邻的正方形(没有对角线)比我现在的那个还要大。
For example:
0 1 2 3 4
0 { 5 13 2 5 2
1 58 24 32 3 24
2 2 7 33 1 7
3 45 40 37 24 70
4 47 34 12 25 2
5 52 56 68 76 100}
所以一个有效的解决方案是: (0,0) - >(0,1) - >(1,1) - >(2,1) - >(2,2) - >(2,3) - >(3 ,1) - >(3,0) - >(0,4) - >(0,5) - >(5,1) - >(5,2) - >(5,3 ) - >(5,4)
该方法将返回14,因为这是最短路径。
我必须只使用递归方法(没有循环)。
这是我到目前为止所提出的,但我不知道如何找出哪个是最短的。
Public static int shortestPath(int[][]mat)
{
int length=0;
int i=0;
int j=0;
shortestPath(mat, length, i, j);
}
Private static int shortestPath(int[][]math, int length, int i, int j)
{
if((i==mat.length)||(j==mat[i].length))
return length;
if(shortestPath(mat, length, i+1, j) > shortestPath(mat, length, i, j))
return length +1;
if(shortestPath(mat, length, i, j+1) > shortestPath(mat, length, i, j))
return length +1;
if shortestPath(mat, length, i-1, j) > shortestPath(mat, length, i, j))
return length +1;
if shortestPath(mat, length, i, j-1) > shortestPath(mat, length, i, j))
return length +1;
}
我不确定这是否是这样做的方式,如果是:我怎么知道哪种方式最短,因为现在它会返回所有可能的方式并将它们添加(我想)。 另外,我想我应该添加一些关于到达矩阵右下角的内容。
代码不应该太复杂。
答案 0 :(得分:1)
我不确定进入下一个最小值的方法是否最短,但无论如何:
public class Pathfinder {
private int[][] matrix;
private int matrixLenghtI;
private int matrixLenghtJ;
public Pathfinder(int[][] matrix, int matrixLenghtI, int matrixLenghtJ) {
this.matrix = matrix;
this.matrixLenghtI = matrixLenghtI;
this.matrixLenghtJ = matrixLenghtJ;
}
public static void main(String[] args) {
int matrixLenghtI = 6;
int matrixLenghtJ = 5;
int[][] matrix1 = { { 3, 13, 15, 28, 30 }, { 40, 51, 52, 29, 30 }, { 28, 10, 53, 54, 54 },
{ 53, 12, 55, 53, 60 }, { 70, 62, 56, 20, 80 }, { 80, 81, 90, 95, 100 } };
int[][] matrix2 = { { 5, 13, 2, 5, 2 }, { 58, 24, 32, 3, 24 }, { 2, 7, 33, 1, 7 }, { 45, 40, 37, 24, 70 },
{ 47, 34, 12, 25, 2 }, { 52, 56, 68, 76, 100 } };
Pathfinder finder1 = new Pathfinder(matrix1, matrixLenghtI, matrixLenghtJ);
finder1.run();
Pathfinder finder2 = new Pathfinder(matrix2, matrixLenghtI, matrixLenghtJ);
finder2.run();
}
private void run() {
int i = 0;
int j = 0;
System.out.print("(" + i + "," + j + ")");
System.out.println("\nLength: " + find(i, j));
}
private int find(int i, int j) {
int value = matrix[i][j];
int[] next = { i, j };
int smallestNeighbour = 101;
if (i > 0 && matrix[i - 1][j] > value) {
smallestNeighbour = matrix[i - 1][j];
next[0] = i - 1;
next[1] = j;
}
if (j > 0 && matrix[i][j - 1] < smallestNeighbour && matrix[i][j - 1] > value) {
smallestNeighbour = matrix[i][j - 1];
next[0] = i;
next[1] = j - 1;
}
if (i < matrixLenghtI - 1 && matrix[i + 1][j] < smallestNeighbour && matrix[i + 1][j] > value) {
smallestNeighbour = matrix[i + 1][j];
next[0] = i + 1;
next[1] = j;
}
if (j < matrixLenghtJ - 1 && matrix[i][j + 1] < smallestNeighbour && matrix[i][j + 1] > value) {
smallestNeighbour = matrix[i][j + 1];
next[0] = i;
next[1] = j + 1;
}
System.out.print("->(" + next[0] + "," + next[1] + ")");
if (i == matrixLenghtI - 1 && j == matrixLenghtJ - 1)
return 1;
return find(next[0], next[1]) + 1;
}
}
输出:
(0,0)->(0,1)->(0,2)->(0,3)->(1,3)->(1,4)->(2,4)->(3,4)->(4,4)->(5,4)->(5,4)
Length: 10
(0,0)->(0,1)->(1,1)->(1,2)->(2,2)->(3,2)->(3,1)->(3,0)->(4,0)->(5,0)->(5,1)->(5,2)->(5,3)->(5,4)->(5,4)
Length: 14
答案 1 :(得分:1)
我真的很喜欢这个问题。不幸的是我多年没有在Java工作,所以这个答案是伪Java,你必须修复一些语法。可能一些函数参数应该是引用而不是副本;你会搞清楚的(更新:我在下面的python中添加了一个TESTED版本)。
// just a little thing to hold a set of coordinates
class Position
{
// not bothering with private / getters
public int x ;
public int y ;
public constructor (int x, int y)
{
this.x = x ;
this.y = y ;
}
}
class PathFinder
{
public void main (void)
{
// create a path with just the start position
start = new Position(0, 0) ;
path = new Vector() ;
path.add(start) ;
// create an empty path to contain the final shortest path
finalPath = new Vector() ;
findPath(path, finalPath) ;
print ("Shortest Path: ") ;
showPath (finalPath) ;
}
private void showPath (Vector path) {
// print out each position in the path
iter = path.iterator() ;
while (pos = iter.next()) {
print ("(%, %) ", pos.x, pos.y);
}
// print out the length of the path
print (" Length: %\n", path.size()) ;
}
// recursive function to find shortest path
private void findPath (Vector path, Vector finalPath)
{
// always display the current path (it should never be the same path twice)
showPath(path) ;
// where are we now?
here = path.lastElement() ;
// does the current path find the exit (position 4,5)?
if (here.x == 4 && here.y == 5) {
if (finalPath.size() == 0) {
//finalPath is empty, put the current path in finalPath
finalPath = path ;
} else {
// some other path found the exit already. Which path is shorter?
if (finalPath.size() > path.size()) {
finalPath = path ;
}
}
// either way, we're at the exit and this path goes no further
return ;
}
// path is not at exit; grope in all directions
// note the code duplication in this section is unavoidable
// because it may be necessary to start new paths in three
// directions from any given position
// If no new paths are available from the current position,
// no new calls to findPath() will happen and
// the recursion will collapse.
if (here.x > 0 && matrix[here.x-1][here.y] > matrix[here.x][here.y]) {
// we can move left
newPos = new Position(here.x-1, here.y) ;
newPath = path ;
newPath.add (newPos) ;
findPath(newPath, finalPath) ;
}
if (here.x < 4 && matrix[here.x+1][here.y] > matrix[here.x][here.y]) {
// we can move right
newPos = new Position(here.x+1, here.y) ;
newPath = path ;
newPath.add (newPos) ;
findPath(newPath, finalPath) ;
}
if (here.y > 0 && matrix[here.x][here.y-1] > matrix[here.x][here.y]) {
// we can move up
newPos = new Position(here.x, here.y-1) ;
newPath = path ;
newPath.add (newPos) ;
findPath(newPath, finalPath) ;
}
if (here.y < 5 && matrix[here.x][here.y+1] > matrix[here.x][here.y]) {
// we can move down
newPos = new Position(here.x, here.y+1) ;
newPath = path ;
newPath.add (newPos) ;
findPath(newPath, finalPath) ;
}
}
}
这是python中相同算法的测试版本。 (我注意到使用x, y
作为坐标有点误导。x
实际上是“垂直的”而y
是“水平的”,数组的索引方式就是它。我已经设置了一个矩阵,有四条通往出口的路径和几条死路。)
import copy, sys
matrix = [
[5, 13, 17, 58, 2],
[17, 24, 32, 3, 24],
[23, 7, 33, 1, 7],
[45, 40, 37, 38, 70],
[47, 34, 12, 25, 2],
[52, 56, 68, 76, 100]]
def showPath(path):
for position in path:
sys.stdout.write("(" + str(position[0]) + ", " + str(position[1]) + "), ")
sys.stdout.write("\n\n")
sys.stdout.flush()
def findPath(path):
#showPath(path)
global finalPath
x = path[-1][0]
y = path[-1][1]
if x == 5 and y == 4:
showPath(path)
if len(finalPath) == 0 or len(finalPath) > len (path):
finalPath[:] = copy.deepcopy(path)
return
if x > 0 and matrix[x-1][y] > matrix[x][y]:
# we can move up
newPath = copy.deepcopy(path)
newPath.append([x-1, y])
findPath(newPath)
if x < 5 and matrix[x+1][y] > matrix[x][y]:
# we can move down
newPath = copy.deepcopy(path)
newPath.append([x+1, y])
findPath(newPath)
if y > 0 and matrix[x][y-1] > matrix[x][y]:
# we can move left
newPath = copy.deepcopy(path)
newPath.append([x, y-1])
findPath(newPath)
if y < 4 and matrix[x][y+1] > matrix[x][y]:
# we can move right
newPath = copy.deepcopy(path)
newPath.append([x, y+1])
findPath(newPath)
path = []
path.append([0, 0])
finalPath = []
findPath(path)
print "Shortest Path: " + str(len(finalPath)) + " steps.\n"
showPath(finalPath)
如果您取消注释showPath()
中的第一个findPath()
来电,您可以看到每一步,看看死胡同被放弃的地方。如果只显示到达出口的路径,则输出如下所示:
(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),
(0, 0), (1, 0), (1, 1), (1, 2), (2, 2), (3, 2), (3, 1), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),
(0, 0), (0, 1), (1, 1), (1, 2), (2, 2), (3, 2), (3, 1), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),
(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),
Shortest Path: 10 steps.
(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),
答案 2 :(得分:0)
在这里,您可以为所有可能性构建一棵树,然后采用最短的树。内部有一个循环用于跟踪结果,但你也可以用一些丑陋的ifs来解决这个问题......
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
public class BetterPathfinder {
public class Comperator implements Comparator<Path> {
@Override
public int compare(Path o1, Path o2) {
return o1.getValue().compareTo(o2.getValue());
}
}
public class Path {
private Integer lenght;
TreeMap<Integer, String> trace = new TreeMap<>();
public Path(int lenght) {
this.lenght = lenght;
}
public Path(Path find, int i, int j) {
this.lenght = find.getValue() + 1;
this.trace.putAll(find.getTrace());
this.trace.put(lenght, "(" + i + "," + j + ")");
}
private Map<Integer, String> getTrace() {
return trace;
}
public Integer getValue() {
return lenght;
}
@Override
public String toString() {
String res = "end";
for (Entry<Integer, String> is : trace.entrySet()) {
res = is.getValue() + "->" + res;
}
return res;
}
}
private int[][] matrix;
private int matrixLenghtI;
private int matrixLenghtJ;
public BetterPathfinder(int[][] matrix, int matrixLenghtI, int matrixLenghtJ) {
this.matrix = matrix;
this.matrixLenghtI = matrixLenghtI;
this.matrixLenghtJ = matrixLenghtJ;
}
public static void main(String[] args) {
int matrixLenghtI = 6;
int matrixLenghtJ = 5;
int[][] matrix1 = { { 3, 13, 15, 28, 30 }, { 40, 51, 52, 29, 30 }, { 28, 10, 53, 54, 54 },
{ 53, 12, 55, 53, 60 }, { 70, 62, 56, 20, 80 }, { 80, 81, 90, 95, 100 } };
int[][] matrix2 = { { 5, 13, 2, 5, 2 }, { 58, 24, 32, 3, 24 }, { 2, 7, 33, 1, 7 }, { 45, 40, 37, 24, 70 },
{ 47, 34, 12, 25, 2 }, { 52, 56, 68, 76, 100 } };
BetterPathfinder finder1 = new BetterPathfinder(matrix1, matrixLenghtI, matrixLenghtJ);
finder1.run();
BetterPathfinder finder2 = new BetterPathfinder(matrix2, matrixLenghtI, matrixLenghtJ);
finder2.run();
}
private void run() {
int i = 0;
int j = 0;
System.out.println(new Path(find(i, j), i, j));
}
private Path find(int i, int j) {
int value = matrix[i][j];
int[] next = { i, j };
ArrayList<Path> test = new ArrayList<>();
if (i == matrixLenghtI - 1 && j == matrixLenghtJ - 1)
return new Path(1);
if (i > 0 && matrix[i - 1][j] > value) {
next[0] = i - 1;
next[1] = j;
test.add(new Path(find(next[0], next[1]), next[0], next[1]));
}
if (j > 0 && matrix[i][j - 1] > value) {
next[0] = i;
next[1] = j - 1;
test.add(new Path(find(next[0], next[1]), next[0], next[1]));
}
if (i < matrixLenghtI - 1 && matrix[i + 1][j] > value) {
next[0] = i + 1;
next[1] = j;
test.add(new Path(find(next[0], next[1]), next[0], next[1]));
}
if (j < matrixLenghtJ - 1 && matrix[i][j + 1] > value) {
next[0] = i;
next[1] = j + 1;
test.add(new Path(find(next[0], next[1]), next[0], next[1]));
}
if (test.isEmpty()) {
return new Path(100);
}
return Collections.min(test, new Comperator());
}
}
结果:
(0,0)->(1,0)->(1,1)->(1,2)->(2,2)->(3,2)->(4,2)->(5,2)->(5,3)->(5,4)->end
(0,0)->(0,1)->(1,1)->(1,2)->(2,2)->(3,2)->(3,1)->(3,0)->(4,0)->(5,0)->(5,1)->(5,2)->(5,3)->(5,4)->end
答案 3 :(得分:0)
你想要一个递归策略。一个非常简单但很昂贵的方法就是简单地充斥电路板。类似&#34;尝试每条可能的路径并计算距离&#34; 。
你可以通过想象移动卵石来递归地做到这一点。
public int shortestPath(Point src, Point dest) {
if (src.equals(dest)) {
return 0;
}
// You need to do some bound checks here
int left = shortestPath(new Point(src.x - 1, src.y), dest);
int right = shortestPath(new Point(src.x + 1, src.y), dest);
int up = shortestPath(new Point(src.x, src.y + 1), dest);
int down = shortestPath(new Point(src.x, src.y - 1), dest);
// Decide for the direction that has the shortest path
return min(left, right, up, down) + 1;
}
如果您对解决方案所代表的路径感兴趣,则可以在创建时跟踪路径。为此,您只需要保存min
确定的方向。
我需要在我的计算机科学研究中解决类似的任务。我们需要计算knight
chess board
对达到给定destination
所需的最短移动量。也许这也可以帮助你:http://pastebin.com/0xwMcQgj
答案 4 :(得分:0)
职位等级:
/**
* Represents a position in the matrix.
*/
public class Position {
final private int x;
final private int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public String toString() {
return "(" + x + ", " + y + ')';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Position position = (Position) o;
if (x != position.x) return false;
return y == position.y;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
董事会成员:
/**
* A board represents all of the locations in the matrix. It provides a simple interface to getting
* the value in a position, and tracking the height and width of the matrix.
*/
public class Board {
final int [][] board;
public Board(int[][] board) {
this.board = board;
}
final int positionValue(Position position) {
return this.board[position.getY()][position.getX()];
}
final int getWidth() {
return board[0].length;
}
final int getHeight() {
return board.length;
}
}
路径查找器类:
import java.util.ArrayList;
import java.util.List;
/**
* Find the shortest path from a starting point to ending point in a matrix, assuming you can
* only move to a position with a greater value than your current position.
*/
public class PathFinder {
final private Board board;
final private Position start;
final private Position end;
public PathFinder(Board board, int startX, int startY, int endX, int endY) {
this.board = board;
this.start = new Position(startX, startY);
this.end = new Position(endX, endY);
}
/**
* Gets the shortest path from the start to end positions. This method
* takes all of the paths, then determines which one is shortest and returns that.
*
* @return the shortest path from the start to end positions.
*/
public List<Position> shortestPath() {
List<List<Position>> allPaths = this.getAllPaths();
System.out.println("Paths found: " + allPaths.size());
List<Position> shortestPath = null;
for (List<Position> path : allPaths) {
if (shortestPath == null) {
shortestPath = path;
}
else if (shortestPath.size() > path.size()) {
shortestPath = path;
}
}
return shortestPath;
}
/**
* Convenience method for starting the getAllPaths process.
*
* @return all of the paths from the start to end positions
*/
private List<List<Position>> getAllPaths() {
List<List<Position>> paths = new ArrayList<List<Position>>();
return this.getAllPaths(paths, new ArrayList<Position>(), start);
}
/**
* Gets all of the paths from the start to end position. This is done recursively by visiting every
* position, while following the rules that you can only move to a position with a value greater
* than the position you're currently on. When reaching the end position, the path is added to
* the list of all found paths, which is returned.
*
* @param paths the current list of all found paths.
* @param path the current path
* @param position the current position
* @return all paths from the start to end positions
*/
private List<List<Position>> getAllPaths(List<List<Position>> paths, List<Position> path, Position position) {
path.add(position);
if (position.equals(end)) {
paths.add(path);
return paths;
}
//x+
if (position.getX() + 1 < board.getWidth()) {
Position xp = new Position(position.getX() + 1, position.getY());
if (board.positionValue(position) < board.positionValue(xp)) {
getAllPaths(paths, new ArrayList<Position>(path), xp);
}
}
//x-
if (position.getX() - 1 >= 0) {
Position xm = new Position(position.getX() - 1, position.getY());
if (board.positionValue(position) < board.positionValue(xm)) {
getAllPaths(paths, new ArrayList<Position>(path), xm);
}
}
//y+
if (position.getY() + 1 < board.getHeight()) {
Position yp = new Position(position.getX(), position.getY() + 1);
if (board.positionValue(position) < board.positionValue(yp)) {
getAllPaths(paths, new ArrayList<Position>(path), yp);
}
}
//y-
if (position.getY() - 1 >= 0) {
Position ym = new Position(position.getX(), position.getY() - 1);
if (board.positionValue(position) < board.positionValue(ym)) {
getAllPaths(paths, new ArrayList<Position>(path), ym);
}
}
return paths;
}
/**
* Run the example then print the results.
*
* @param args na
*/
public static void main(String[] args) {
int [][] array = {{5, 13, 2, 5, 2},
{14, 24, 32, 3, 24},
{15, 7, 33, 1, 7},
{45, 40, 37, 24, 70},
{47, 34, 12, 25, 2},
{52, 56, 68, 76, 100}
};
final Board board = new Board(array);
final Position end = new Position(board.getWidth()-1, board.getHeight() - 1);
final PathFinder pathFinder = new PathFinder(board, 0, 0, board.getWidth()-1, board.getHeight()-1);
final List<Position> path = pathFinder.shortestPath();
System.out.println("Shortest Path: ");
for (Position position : path) {
if (!position.equals(end)) {
System.out.print(position + " -> ");
}
else {
System.out.println(position);
}
}
System.out.println();
}
}
答案 5 :(得分:0)
public class shortestPath{
public static int shortestPath(int[][] mat){
if(mat == null || mat.length == 0 || mat[0].length == 0)
return 0;
else {
int n = shortestPath(mat, 0, 0, 0);
return (n == mat.length*mat.length+1 ) ? 0 : n;
}
}
private static int shortestPath(int[][]mat, int row, int col,int prev){
if (!valid(mat,row,col) || !(mat[row][col] > prev)){
return mat.length*mat.length+1;
} else if(row == mat.length - 1 && col == mat[row].length - 1) {
return 1;
} else {
return minimum(shortestPath(mat,row-1,col, mat[row][col]),
shortestPath(mat,row+1,col, mat[row][col]),
shortestPath(mat,row,col-1, mat[row][col]),
shortestPath(mat,row,col+1, mat[row][col])) + 1;
}
}
private static boolean valid(int[][]mat,int row, int col){
if(row < 0 || col < 0 || col > mat[0].length-1 || row > mat.length-1)
return false;
else
return true;
}
private static int minimum(int x, int y, int t, int z){
int min1 = (x > y)? y : x;
int min2 = (t > z)? z : t;
return (min1 > min2)? min2 : min1;
}
public static void main(String[] args){
int maze[][] = {
{ 3, 13, 15, 28, 30},
{ 40, 51, 52, 29, 30},
{ 28, 10, 53, 54, 53},
{ 53, 12, 55, 53, 60},
{ 70, 62, 56, 20, 80},
{ 81, 81, 90, 95, 100}};
System.out.println(shortestPath(maze));
}
}
答案 6 :(得分:0)
这是我解决它的方法,注意在你的例子中我们应该得到 16
public static void main(String[] args)
{
int[][] mat =
{
{ 3, 13, 15, 28, 30 },
{ 40, 51, 52, 29, 30 },
{ 28, 10, 53, 54, 53 },
{ 53, 12, 55, 53, 60 },
{ 70, 62, 56, 20, 80 },
{ 80, 81, 90, 95, 100 }
};
System.out.println(shortestPath(mat)); // 10
int[][] mat1 =
{
{0, 1, 2, 3, 4 },
{0, 5, 13, 2, 5, 2},
{1, 58, 24, 32, 3, 24} ,
{2, 2 , 7, 33, 1, 7} ,
{3, 45, 40, 37, 24, 70},
{4, 47, 34, 12, 25, 2},
{5, 52, 56, 68, 76, 100}
};
System.out.println(shortestPath(mat1)); // 16
}
public static int shortestPath(int[][] mat)
{
return shortestPath(mat, 0, 0, mat[0][0] - 1, 0);
}
private static int shortestPath(int[][] mat, int row, int col, int prev, int counter)
{
if (row < 0 || row == mat.length || col < 0 || col == mat[row].length) // boundaries
return Integer.MAX_VALUE;
if (mat[row][col] <= prev || mat[row][col] == -999) // if the sequence is not ascending or if we have been in this cell before
return Integer.MAX_VALUE;
if (row == mat.length - 1 && col == mat[row].length - 1)
return counter + 1;
int temp = mat[row][col];
mat[row][col] = -999;
int up = shortestPath(mat, row - 1, col, temp, counter + 1); // go up and count
int down = shortestPath(mat, row + 1, col, temp, counter + 1);
int left = shortestPath(mat, row, col - 1, temp, counter + 1);
int right = shortestPath(mat, row, col + 1, temp, counter + 1);
mat[row][col] = temp;
return Math.min(Math.min(up, down), Math.min(left, right)); // get the min
}