0

我一直在尝试通过广度优先搜索来解决这个问题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

4

2 回答 2

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 的新位置。
于 2013-03-16T01:32:25.450 回答
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;
}
}

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

于 2013-03-16T08:47:05.030 回答