使用BFS进行迷宫?

时间:2013-03-16 00:47:05

标签: java

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

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

2 个答案:

答案 0 :(得分: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. 找到一块糖果后,您需要找到下一个最近的当前位置,所以请将当前位置视为新start另一个BFS。

答案 1 :(得分:0)

我刚刚以你的方式解决了问题,&#34;贪心&#34;这里的方式是代码

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;
}
}

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