2013-03-16 84 views
0

我一直试图用广度优先搜索来解决这个问题http://dwite.ca/questions/haunted_house.html,但是我无法得到所有的测试用例都是正确的,我认为问题在于,它只会计算到最后的直接最短路径,将计算任何糖果打开,但它不会指望通过这里的糖果的最短路径是代码在迷宫中使用BFS?

import java.io.*; 
import java.util.*; 

public class HalloweenCandy { 

    static int n, candy; 
    static int minsteps, maxcandy; 
    static int totCandies=0; 
    public static void main(String[] args) throws FileNotFoundException { 
     Scanner s = new Scanner(new File("C:\\Users\\Daniel\\Desktop\\Java\\HalloweenCandy\\src\\halloweencandy\\DATA5.txt")); 

     while (s.hasNext()) { 
      n=Integer.parseInt(s.nextLine().trim()); 
      char[][]maze=new char[n][n]; 
      int xStart =0; 
      int yStart =0; 

      for(int y=0;y<n;++y){ 
       String text = s.nextLine().trim(); 
       for(int x=0;x<n;++x){ 

        maze[x][y]=text.charAt(x); 
        if(maze[x][y]=='B'){ 
         xStart=x; 
         yStart=y; 
        } 
       } 
      } 
      candy=0; 
      minsteps=0; 
      BFS(maze,xStart,yStart); 
      System.out.println(candy+" "+minsteps); 
     } 
    } 
    public static void BFS(char[][]maze,int xStart,int yStart){ 
     Queue<int[]>queue=new LinkedList<int[]>(); 
     int start[]={xStart,yStart,0,0}; 
     queue.add(start); 

     while(queue.peek()!=null){ 
      int[]array=queue.poll(); 
      int x=array[0];int y=array[1]; 

      if(x<0||y<0||y>n-1||x>n-1)continue; 
      if(maze[x][y]=='#')continue; 
      if(maze[x][y]=='*'){     
       candy++;    
       minsteps=array[2]; 
       maze[x][y]='.'; 
      } 
      if(maze[x][y]>='a'&&maze[x][y]<='f'){ 
       if(candy <maze[x][y]-'a'+1)continue; 
      } 
      int[][]points = {{0,1},{1,0},{-1,0},{0,-1}}; 
      for(int i=0;i<4;++i){ 
       int sta[]={x+points[i][0],y+points[i][1],array[2]+1}; 
       queue.add(sta); 
      } 
      maze[x][y]='#'; 
     } 

    } 
} 

,这里是测试用例 http://dwite.ca/home/testcase/232.html

回答

1

你在写轨道,但你错过了重要的事情

while(queue.peek()!=null){ 
     int[]array=queue.poll(); 
     int x=array[0];int y=array[1]; 

     if(x<0||y<0||y>n-1||x>n-1)continue; 
     if(maze[x][y]=='#')continue; 
     if(maze[x][y]=='*'){     
      candy++;    
      minsteps=array[2]; 
      maze[x][y]='.'; 
     } 
     if(maze[x][y]>='a'&&maze[x][y]<='f'){ 
      if(candy <maze[x][y]-'a'+1)continue; 
     } 
     int[][]points = {{0,1},{1,0},{-1,0},{0,-1}}; 
     for(int i=0;i<4;++i){ 
      int sta[]={x+points[i][0],y+points[i][1],array[2]+1}; 
      queue.add(sta); 
     } 
     maze[x][y]='#'; // <== this part is wrong 
    } 

你在做的最后一项任务是让每一个方格都进入墙壁。如果你能够在没有回溯的情况下穿过迷宫,这将是正确的方法,但事实并非如此。相反,你想要做的是确保你不会退缩,直到你拿起一块新的糖果。所以,尝试这样的代替:

maze[x][y]='a'+candy; 

这样,一旦你拿起一块新的糖果广场将再次可用。

但是,这里仍然存在问题。想想BFS将如何在此地图上的工作:

3 
... 
*B* 
... 

如果[0,0]是左上图块,那么你的BFS算法将参观瓷砖顺序如下:[1,2],[2 ,1],[0,1],[1,0]。那有什么问题?比利正在他所有的邻居广场之间跳跃!你真正想要他做的是每次他拿到一块新糖时重新启动BFS。我会让你知道如何做到这一点。

编辑

这里是要遵循的基本算法:

  1. 开始在start位置。
  2. 使用BFS搜索最近的一块糖果。在BFS找到的第一块糖果是最近的(或者最近并列的)!
  3. 找到一块糖之后,你需要找到下一个最接近一块你当前位置,因此可以看作是另一个BFS新start您的当前位置。
+0

如此贪婪的方法?或者当你得到糖果时你的意思是继续bfs循环吗? – ultrainstinct 2013-03-16 01:37:56

+0

@Panphobia - 查看我上面的修改。 – DaoWen 2013-03-16 01:55:24

+0

类似[Star,Dot,B,Star,Star,Star]不会起作用,因为我不能使用星号和点,因为它阻止了它的一部分。因为那么最佳的解决方案是从最左边的星球开始 – ultrainstinct 2013-03-16 02:03:59

0

我刚刚完成解决它自己的方式,将“贪婪”这里的方法是代码

import java.io.*; 
import java.util.*; 

public class HalloweenCandy { 

static int n, candy; 
static int minsteps, maxcandy; 
static int totCandies = 0; 
static boolean[][] is; 

public static void main(String[] args) throws FileNotFoundException { 
    Scanner s = new Scanner(new File("C:\\Users\\Daniel\\Desktop\\Java\\HalloweenCandy\\src\\halloweencandy\\DATA5.txt")); 
    while (s.hasNext()) { 
     n = Integer.parseInt(s.nextLine().trim()); 
     char[][] maze = new char[n][n]; 
     is = new boolean[n][n]; 
     int xStart = 0; 
     int yStart = 0; 
     for (int y = 0; y < n; ++y) { 
      String text = s.nextLine().trim(); 
      for (int x = 0; x < n; ++x) { 

       maze[x][y] = text.charAt(x); 
       if (maze[x][y] == 'B') { 
        xStart = x; 
        yStart = y; 
       } 
      } 
     } 
     candy = 0; 
     int tot = 0; 
     int y = 0, x = 0; 
     x = xStart; 
     y = yStart; 
     for (int j = 0; j < n; ++j) { 
      for (int i = 0; i < n; ++i) { 
       is[i][j] = false; 
      } 
     } 
     while (true) { 
      char[][] grid = new char[n][n]; 
      for (int j = 0; j < n; ++j) { 
       for (int i = 0; i < n; ++i) { 
        grid[i][j] = maze[i][j]; 
       } 
      } 
      int lol[] = BFS(grid, x, y); 
      if (lol[0] == -1) { 
       break; 
      } 
      y = lol[2]; 
      x = lol[1]; 
      tot += lol[0]; 
     } 
     System.out.println(candy + " " + tot); 
    } 
} 

public static int[] BFS(char[][] maze, int xStart, int yStart) { 
    Queue<int[]> queue = new LinkedList<int[]>(); 
    int start[] = {xStart, yStart, 0, 0}; 
    queue.add(start); 
    while (queue.peek() != null) { 
     int[] array = queue.poll(); 
     int x = array[0]; 
     int y = array[1]; 
     if (x < 0 || y < 0 || y > n - 1 || x > n - 1) { 
      continue; 
     } 
     if (maze[x][y] == '#') { 
      continue; 
     } 
     if (maze[x][y] == '*' && !is[x][y]) { 
      is[x][y] = true; 
      candy++; 
      int sta[] = {array[2], x, y}; 
      return sta; 

     } 
     if (maze[x][y] >= 'a' && maze[x][y] <= 'f') { 
      if (candy < maze[x][y] - 'a' + 1) { 
       continue; 
      } 
     } 
     int[][] points = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; 
     for (int i = 0; i < 4; ++i) { 
      int sta[] = {x + points[i][0], y + points[i][1], array[2] + 1}; 
      queue.add(sta); 
     } 
     maze[x][y] = '#'; 
    } 
    int sta[] = {-1}; 
    return sta; 
} 
} 

我想现在弄清楚如何解决它的动态的方式,解决我只给了适用于某些情况,但不是全部。