我有一个问题,我正在努力练习,而且我无法弄清楚如何为它编写递归算法。我有一个像这样的文件:
4
(())
()((
(()(
))))
此问题来自USACO。 http://www.usaco.org/index.php?page=viewproblem2&cpid=189
问题陈述在下面复制粘贴:
虽然Bessie奶牛找到了每一串平衡的括号 在美学上令人愉悦,她特别喜欢她的弦乐 电话"完美"平衡 - 由一串(' s)组成 由一串具有相同长度的字符串组成。例如:
(((())))
有一天,在走进谷仓的时候,贝茜发现了一个N x N网格 马蹄铁在地面上,每个马蹄铁的方向都是这样的 它看起来像(或)。从左上角开始 这个网格,贝茜想要四处走动捡马蹄铁 她拾起的弦完全平衡。 请帮助她 计算她能做的最长的完美平衡弦的长度 获得
在每一步中,贝茜可以向上,向下,向左或向右移动。她只能 移动到包含马蹄铁的网格位置,当她这样做时 这一点,她拿起马蹄铁,以便她再也不能回去了 到同一个地方(因为它现在没有马蹄铁)。她一开始 在网格的左上角拾起马蹄铁。贝西 只拿起一系列形成完美平衡的马蹄铁 因此,她可能无法拿起所有的 网格中的马蹄铁。
我在尝试弄清楚如何创建一个以递归方式找到最佳路径的算法时遇到问题。任何人都可以指出我正确的方向,或者有任何我可以看到的例子来获得一个想法?我一直在搜索,但我发现的所有例子都是从一个点到另一个点,并没有在矩阵/数组中找到所有可能的路径。
package bessiehorseshoe;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BessieHorseShoe {
int answer = 0;
int matrixSize = 0;
public static void main(String[] args) throws IOException {
BessieHorseShoe goBessieGo = new BessieHorseShoe();
}
BessieHorseShoe() throws IOException {
int rowFilled = 0;
int currentColumn = 0;
int character = 0;
BufferedReader inputFile = new BufferedReader(new FileReader("hshoe.in"));
String inputLine = inputFile.readLine();
matrixSize = Character.digit(inputLine.charAt(0), 10);
System.out.println(matrixSize);
char[][] pMatrix = new char[matrixSize][matrixSize];
while ((character = inputFile.read()) != -1) {
char c = (char) character;
if (c == '(' || c == ')') {
pMatrix[rowFilled][currentColumn] = c;
System.out.print(pMatrix[rowFilled][currentColumn]);
rowFilled++;
if (rowFilled == matrixSize) {
currentColumn++;
rowFilled = 0;
System.out.println();
}
}
}
matchHorseShoes(pMatrix);
}
public int matchHorseShoes(char[][] pMatrix) {
if (pMatrix[0][0] == ')') {
System.out.println("Pattern starts with ')'. No possible path!");
return 0;
}
System.out.println("Works");
return 0;
}
}
答案 0 :(得分:0)
以下算法将解决您的问题。您还可以使用memoization来加快运行时间。 这个想法很简单:
所有其余代码都是语法糖。 (从返回的项目列表中获取您想要的输出是非常简单的。)
import java.util.LinkedList;
import java.util.List;
public class USACO {
static class Path {
public List<String> items;
public int value;
public Path() {
this.items = new LinkedList<String>();
this.value = 0;
}
}
public static void main(final String[] args) {
final int n = 5;
final String[][] input = new String[n][n];
// Create a random input of size n
for (int y = 0; y < n; y++) {
for (int x = 0; x < n; x++) {
input[y][x] = Math.random() < 0.5 ? "(" : ")";
System.out.print(input[y][x] + " ");
}
System.out.println();
}
final Path bestPath = longestPath(n, input, 0, 0, 0, 0, input[0][0] == "(");
System.out.println("Max:" + bestPath.value + "\n" + bestPath.items);
}
public static Path longestPath(final int n, final String[][] input, final int x, final int y, int numberOpened, int numberClosed,
final boolean wasOpening) {
if (input == null) {
return new Path();
} else if (!wasOpening && (numberClosed >= numberOpened)) { // Reached a solution
final Path path = new Path();
path.value = numberOpened;
path.items.add("(" + x + "," + y + ")");
return path;
} else if ((x < 0) || (y < 0) || (x >= n) || (y >= n)) { // Out of bound
return new Path();
} else if (input[y][x] == "") { // Already visited this item
return new Path();
} else {
final String parenthese = input[y][x];
// Increment the number of consecutive opened or closed visited
if (parenthese.equals("(")) {
numberOpened++;
} else {
numberClosed++;
}
input[y][x] = ""; // Mark as visited
Path bestPath = new Path();
bestPath.value = Integer.MIN_VALUE;
// Explore the other items
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
if (((dy == 0) || (dx == 0)) && (dy != dx)) { // go only up, down, left, right
final boolean opening = (parenthese == "(");
if (wasOpening || !opening) {
// Find the longest among all the near items
final Path possiblePath = longestPath(n, input, x + dx, y + dy, numberOpened, numberClosed, opening);
if (possiblePath.value > bestPath.value) {
bestPath = possiblePath;
bestPath.items.add("(" + x + "," + y + ")");
}
}
}
}
}
input[y][x] = parenthese; // mark as not visited
return bestPath;
}
}
}