2016-07-29 17 views
1

私はこの問題を試みましたが、何らかの理由でそれが正しく出力されませんでした。一連の文字列が与えられた場合、文字列が1つの "R"(ラット)、1つの "C"(チーズ)、複数の "X"(通過できないブロック) "経路"の任意の点でチーズとの間の(ユークリッド)距離を増やさずに、ラットがチーズに行くために取ることができるルートの数を見つけることです。私のコードで間違って見えるもの再帰を使用してJavaで迷路を解決する

public class RatRoute { 
private static String[] enc; 
private static int count; 
private static int[] r; 
private static int[] c; 

// Test the program 
public static void main(String[] args) { 
    String[] test = { 
      ".R...", 
      "..X..", 
      "....X", 
      "X.X.X", 
      "...C."}; 
    int num1 = numRoutes(test); 
    System.out.println(num1); 
} 

// Set variables, and call recursive function 
public static int numRoutes(String[] enc) { 
    RatRoute.enc = enc;  
    r = findR(enc); 
    c = findC(enc); 
    recursiveHelper(r[0], r[1]); 
    return count; 
} 

// Recursive 
public static void recursiveHelper(int x, int y) { 

    /*System.out.println(); 
    System.out.println(); 
    for (int k = 0; k < enc.length; k++) { 
     System.out.println(enc[k]); 
    }*/ 

    if(isBlock(x,y)) { 
     return; 
    } else if (isBigger(x,y)) { 
     return; 
    } else if (isCheese(x, y)) { 
     count++; 
     //System.out.println("Found the Cheese! Path number: " + count); 
     //System.out.println(); 
     return; 
    } 

    enc[x] = currentPath(x,y);  
    recursiveHelper(x + 1, y); 
    recursiveHelper(x, y + 1); 
    recursiveHelper(x, y - 1); 
    recursiveHelper(x - 1, y); 
    enc[x] = returnPath(x,y); 

} 

// Change the most recently traveled coordinates into a block 
public static String currentPath(int x, int y) { 
    char[] Chars = enc[x].toCharArray(); 
    Chars[y] = 'X'; 
    String newString = String.valueOf(Chars); 
    return newString;  
} 

// Turn path already traveled from blocks back into a usable path to travel (undo the currentPath method) 
public static String returnPath(int x, int y) { 
    char[] Chars = enc[x].toCharArray(); 
    Chars[y] = '.'; 
    String newString = String.valueOf(Chars); 
    return newString;  
} 

// Check if the next movement is into the cheese 
public static boolean isCheese(int x, int y) { 
    if (enc[x].charAt(y) == 'C') { 
     return true; 
    } else { 
     return false; 
    } 
} 

// Check if the next movement is into a block, or outside the given array 
public static boolean isBlock(int x, int y) { 
    if (x == -1 || y == -1 
      || x >= enc.length || y >= enc[x].length()) { 
     return true; 
    } else if (enc[x].charAt(y) == 'X') { 
     //System.out.println(x + "," + y); 
     return true; 
    } else { 
     return false; 
    } 
} 

// See if the distance between the rat and the cheese has gotten larger or smaller 
public static boolean isBigger(int x, int y) { 
    double rx = r[0]; double ry = r[1]; 
    double cx = c[0]; double cy = c[1]; 

    double originalDist = Math.sqrt(Math.pow(rx-cx, 2) + Math.pow(ry-cy, 2)); 
    double newDist = Math.sqrt(Math.pow(x-cx, 2) + Math.pow(y-cy, 2)); 

    //System.out.println("Orginal Distance: " + originalDist); 
    //System.out.println("New Distance: " + newDist); 

    if (newDist > originalDist) { 
     return true; 
    } else { 
     return false; 
    } 
} 

// Find the variables for the original position of the rat 
public static int[] findR(String[] enc) { 
    for (int i = 0; i < enc.length; i++) { 
     for (int j = 0; j < enc[i].length(); j++) { 
      if (enc[i].charAt(j) == 'R') { 
       int[] coordinates = {i, j}; 
       //System.out.println(coordinates[0] + "," + coordinates[1]); 
       return coordinates;     
      } else { 

      } 
     } 
    } 
    int[] other = {-1, -1}; 
    return other; 
} 

// Find the variables for the original position of the rat 
public static int[] findC(String[] enc) { 
    for (int i = 0; i < enc.length; i++) { 
     for (int j = 0; j < enc[i].length(); j++) { 
      if (enc[i].charAt(j) == 'C') { 
       int[] coordinates = {i, j}; 
       //System.out.println(coordinates[0] + "," + coordinates[1]); 
       return coordinates;     
      } else { 

      } 
     } 
    } 
    int[] other = {-1, -1}; 
    return other; 
} 

}

+0

コード内の特定の例に対する回答は、それが役立つ場合は3となります。 – Steve

答えて

0

のが有用観測から始めましょう:?

[...]その間にあるユークリッド距離(ユークリッド距離)とチョコレート の距離を増やすことなく、

基本的には、ラットがチーズに近づくと、決して遠くに戻ることはないということです。

それでは、ラットX座標言わせ3であるとチーズXは、この座標は、前にチーズを形成するよりも遠くにあることを原因となるので、5ラット(すなわちx = 2)「左折」することはできませんされています。

このため、問題を簡単にする良い方法は、ラットが行くことができる方向を見つけることです。あなたの例では、ラットはチーズから左上にあるので、下または右に移動できるのは、そうでなければチーズから遠ざかるからです。ラットxがチーズxと一致すると、右または左に移動することができなくなります。yも同様です。あなたのコードで

、場合:

r[0] - c[0] = 0 // the rat cannot move on the x any more. 
r[1] - c[1] = 0 // the rat cannot move on the y any more. 

r[0] - c[0] == 0 && r[1] - c[1] == 0 

ラットはチーズに達しました!この場合、成功したルートが見つかったためカウンターを増やすことができます。

これを再帰で実際に実行しましょう。あなたが投稿したコードから は、我々は

findR(enc)で見つかっ)(findC(enc)で見つかった)与えられたcで始まり、与えられたrだから、再帰的方法は、次のようになります。

private void findRoutesFrom(int[] r) { 
    // what directions can the rat go? 
    // if the cheese is on the right of the mouse, xDirection 
    // would be +1. 
    int xDirection = (int) Math.signum(c[0] - r[0]); 
    // if the cheese is below of the mouse, yDirection 
    // would be +1. 
    int yDirection = (int) Math.signum(c[1] - r[1]); 

    // Now, if xDirection is != 0 the rat can attempt to move 
    // in that direction, checking if there's not a block 
    if(xDirection != 0 && !isBlock(r[0] + xDirection, r[1])) { 
     // if it can move in that direction, then use recursion to 
     // find all the possible paths form the new position 
     findRoutesFrom(new int[]{r[0] + xDirection, r[1]}); 
    } 

    // same goes for yDirection 
    if(yDirection != 0 && !isBlock(r[0], r[1] + yDirection)) { 
     findRoutesFrom(new int[]{r[0], r[1] + yDirection}); 
    } 

    // if the rat reaches the cheese, increase the successful 
    // paths counter 
    if(xDirection == 0 && yDirection == 0) { 
     count++; 
    } 
} 

それだそれ!エキュレーデス距離の制約のため、方向が!= 0であるかどうかを確認すれば十分です。なぜなら、それが偽である場合、ラットはそれ以上移動できないからです。

関連する問題