我试图编写一个程序,输出(在控制台中)所有可能的路径((x1,x1) --> (x2,x2) --> etc..
格式),用于从左上角到右下角导航大小为NxN的网格;即从(0,0)到(N-1,N-1)。你只能向下或向右移动;即从(0,0)到(0,1)或到(1,0)。我希望程序在每次找到完整路径集时输出(即所有从左上角到右下角的移动),以及该路径设置是什么。
似乎写这个的最好方法是使用递归方法将每个移动输入到arrayList中(参见buildPath
方法 - 程序中的最后一个方法),这是我在哪里遇到麻烦。
为了使它稍微复杂一些,我还会生成随机网格位置,这些位置是“禁止”#34;因此无法通过。 也就是说,一旦我/我弄清楚如何让这个东西完全适用于任何路径,我就可以为自己完成这部分工作。
如何实现递归方法来确定哪些路径可行?任何帮助都表示赞赏(即使伪代码也比没有好)!
到目前为止,这是我的代码(简单的位是伪代码,以便更容易完成,但请告诉我是否应该填写完整的代码):
import java.util.*;
public class RecursiveAlgorithm {
public static ArrayList<Integer> allPaths = new ArrayList<Integer>();
public static ArrayList<String> pathSet = new ArrayList<String>();
public static int path;
public static int N, M, x = 0, y = 0;
public static String nString, mString;
public static boolean grid[][];
public static int right, down;
@SuppressWarnings("resource")
public static void main(String[] args) {
//sets the current position to (0,0)
right = 0;
down = 0;
Input value of N (size of grid)
Input value of M (number of off-limits locations)
offLimits(N, M); //calls offLimits method to randomly generate off-limits locations
buildPath(right, down, allPaths, N); //calls buildPath method
}
public static void offLimits (int N, int M) {
int mCount = 0;
if (M == 0){
} else {
while (mCount < (M + 1)) {
//int range1 = (max - min) + 1;
int range1 = ((N-1) - 1) + 1;
int range2 = ((N-1) - 0) + 1;
int random1 = (int)((Math.random() * range1) + 1);
int random2 = (int)(Math.random() * range2);
//if an 'off-limits' point is generated at the finish point, move it to either 1 place to the left or 1 place above
if ((random1 == N-1) && (random2 == N-1)) {
int switchSelect = (int)(Math.random() * 2);
while (switchSelect > 0) {
switch (switchSelect){
case 1: random1--;
break;
case 2: random2--;
break;
}
}
}
//sets a grid position to 'off-limits' (i.e. random1 = 1, random2 = 2 --> (1, 2) is 'off-limits')
grid[random1][random2] = true;
//counts the amount of off-limits grid locations generated
mCount++;
}
}
}
public static ArrayList<String> buildPath (int right, int down, ArrayList<Integer> allPaths, int N) {
//Updates path with current location (right, down)
/***** FROM HERE ON IS WHERE I AM HAVING TROUBLE *****/
//Stopping Condition
if ((right == N-1) && (down == N-1)) { //robot cannot go right
allPaths.add(path);
return pathSet;
}
//Recursive Steps
if (right == N-1) { //robot cannot go right
buildPath (right, down + 1, allPaths, N);
} else if (down == N-1) { //robot cannot go down
buildPath (right + 1, down, allPaths, N);
} else { //robot CAN go right or go down
buildPath (right + 1, down, allPaths, N);
//pathSet.add(Integer.toString(right));
//pathSet.add(Integer.toString(down));
buildPath (right, down + 1, allPaths, N);
if (grid[x][y] == false) {
//valid new position (substitute x and y for proposed new path step)
} else if (grid[x][y] == true) {
//off-limits position (substitute x and y for proposed new path step)
}
}
return pathSet;
}
}
答案 0 :(得分:2)
你正走在正确的轨道上,但却走向了一个比需要更复杂的解决方案。这是一种方法,它发现它们允许所有4个罗盘方向(不仅仅是向右和向下)。通过删除代码,了解您可以做到多么简单。
import java.util.LinkedHashSet;
class Experimental {
static class PathFinder {
final int gridSize;
final boolean [] [] isBlocked;
final Coord goal;
final LinkedHashSet<Coord> path = new LinkedHashSet<>();
final Random gen = new Random();
PathFinder(int gridSize, int nBlocked) {
this.gridSize = gridSize;
this.isBlocked = new boolean[gridSize][gridSize];
this.goal = new Coord(gridSize - 1, gridSize - 1);
// This gets really inefficient if nBlocked is too big.
for (int n = 0; n < nBlocked; ++n) {
int x, y;
do {
x = gen.nextInt(gridSize);
y = gen.nextInt(gridSize);
} while (isBlocked[x][y] || (x == gridSize - 1 && y == gridSize - 1));
isBlocked[x][y] = true;
}
}
void searchFrom(Coord coord) {
if (path.contains(coord)) return;
path.add(coord);
if (coord.equals(goal)) System.out.println(path);
if (coord.x > 0 && !isBlocked[coord.x - 1][coord.y])
searchFrom(new Coord(coord.x - 1, coord.y));
if (coord.y > 0 && !isBlocked[coord.x][coord.y - 1])
searchFrom(new Coord(coord.x, coord.y - 1));
if (coord.x < gridSize - 1 && !isBlocked[coord.x + 1][coord.y])
searchFrom(new Coord(coord.x + 1, coord.y));
if (coord.y < gridSize - 1 && !isBlocked[coord.x][coord.y + 1])
searchFrom(new Coord(coord.x, coord.y + 1));
path.remove(coord);
}
void printAllPaths() {
searchFrom(new Coord(0, 0));
}
static class Coord {
final int x, y;
public Coord(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Coord) {
Coord other = (Coord) obj;
return x == other.x && y == other.y;
}
return false;
}
@Override
public int hashCode() {
return Integer.hashCode(x) ^ Integer.hashCode(-y);
}
@Override
public String toString() {
return '(' + Integer.toString(x) + ',' + Integer.toString(y) + ')';
}
}
}
public static void main(String[] args) {
new PathFinder(4, new boolean [] [] {
{ false, false, false, false },
{ false, false, true, false },
{ true, false, false, false },
{ false, false, false, false },
}).printAllPaths();
}
}
一个提示:链接的哈希集是这里路径的合理选择,因为我们需要查看&#34;后退&#34;在每一步,以确保我们不会访问已访问过的位置。该集合使查找O(1),而链接确保维持顺序,正常的散列集不是。你的问题不同。