微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

超出时间限制:BFS

如何解决超出时间限制:BFS

我需要输出从'P'到'G'的最短方向。我已经使用 BFS 来实现它。问题如下图:

输入:'N'维迷宫 '#' - 墙 'G' - 幽灵 'P' - 吃豆子

//Input Maze
8
########
  #    #
# # ## #
# #  #G#
#P   ###
#### # #
#G   #G#
########

输出:N/S/W/E方向
EX) E E E S S W W W

我的代码总是超出时间限制。我无法准确指出问题出在哪里。我的代码如下:
我为方向和坐标创建了一个“点”类。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Maze{
    static char[][] map;
    static boolean[][] visited;
    static int[] dr = {1,-1,0};
    static int[] dc = {0,1};
    static String[] compass = {"S","N","W","E"};
    static int cur_x,cur_y,cur_dist,N;
    static String nswe = "";
    static String curnswe = "";
    static String oldDir,dir;
    static int sx,sy;
    static int shortestdist;
    
    public static class Point{
        int x;
        int y;
        int dist;
        String ns;
        String dir;
        
        public Point(int x,int y,int dist,String oldDir,String dir){
            this.x = x;
            this.y = y;
            this.dist = dist;
            if("".equals(oldDir)) {
                this.ns = dir;
            }
            else { this.ns = oldDir + " " + dir; 
            
            }
            }
    }
    

这是 BFS 方法():

    public static void bfs(int x,String dir){
        Queue<Point> q = new LinkedList<Point>();
        
        q.offer(new Point(x,y,dist,oldDir,dir));
        
        while(!q.isEmpty()){
            
            Point cur = q.poll();
            cur_x = cur.x;
            cur_y = cur.y;
            cur_dist = cur.dist;
            curnswe = cur.ns;
         
            nswe = curnswe;
            
            if(map[cur_x][cur_y]=='G') {
                
                return;
                
            }
                   
                       
            for(int dir1 = 0; dir1<4; dir1++){
                int r = cur_x + dr[dir1];
                int c = cur_y + dc[dir1];
                String d = compass[dir1];
                
                if(r >= 0 && c >= 0 && r < N && c < N){
                    
                    if(map[r][c]!='#')
                        if(!visited[r][c]){
                        
                        q.offer(new Point(r,c,cur_dist+1,curnswe,d));
                        visited[r][c] = true;
                    }
                }
            }
        }
        q.clear();
        
    }
    

这是我输入迷宫、解决(BFS)和打印出方向的代码的主要部分。

public static void main(String[] args) throws IOException{
        
        BufferedReader input = new BufferedReader(new InputStreamReader(system.in));
        BufferedWriter output = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(input.readLine());
        
        N = Integer.parseInt(st.nextToken());
        
        int dist = 1;
        
        map = new char[N][N];
        visited = new boolean[N][N];
        
        for(int i=0;i<N;i++){ 
            
            String line = input.readLine();
            
            for (int j=0; j<N; j++) {
                char t = line.charat(j);
      
                if(t=='P') {sx=i; sy=j;}
                
                map[i][j] = line.charat(j);
                
            }
        }
        
        
            bfs(sx,sy,"","");
        
            output.write(nswe + " ");
            
            output.flush();
    }

}

解决方法

我认为您的代码很好,但未能按照评估人员的要求表现良好。 这意味着您需要更改算法。您是否尝试过 DFS 等其他策略?

public static void main(String[] args) throws IOException {
    BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter output = new BufferedWriter(new OutputStreamWriter(System.out));
    StringTokenizer st = new StringTokenizer(input.readLine());

    N = Integer.parseInt(st.nextToken());
    int dist = 1;
    map = new char[N][N];
    visited = new boolean[N][N];

    for (int i = 0; i < N; i++) {
        String line = input.readLine();
        for (int j = 0; j < N; j++) {
            char t = line.charAt(j);
            if (t == 'P') {
                sx = i;
                sy = j;
            }
            map[i][j] = line.charAt(j);
        }
    }

    long time = System.nanoTime();
    bfs(sx,sy,dist,"",""); // bfs run
    time = System.nanoTime() - time;
    output.write(nswe + "  in:" + time + " with bfs\n");

    nswe = "";
    time = System.nanoTime();
    dfs(sx,new boolean[N][N]); // dfs run
    time = System.nanoTime() - time;
    output.write(nswe + " in:" + time + " with dfs");

    output.flush();
}

private static int shortest = Integer.MAX_VALUE;

public static void dfs(int x,int y,int dist,String dir,boolean[][] vstd) {
    int cur_x = x;
    int cur_y = y;
    vstd = Arrays.copyOf(vstd,vstd.length);
    for (int i = 0; i < vstd.length; i++) {
        vstd[i] = Arrays.copyOf(vstd[i],vstd[i].length);
    }
    String curnswe = dir;
    // System.out.println("\n"+dir);
    if (map[cur_x][cur_y] == 'G') {
        if (shortest >= dist) {
            shortest = dist;
            nswe = curnswe;
        }
        return;
    }
    dist++;
    if (shortest <= dist)
        return;
    for (int dir1 = 0; dir1 < 4; dir1++) {
        int r = cur_x + dr[dir1];
        int c = cur_y + dc[dir1];
        String d = compass[dir1];

        if (r >= 0 && c >= 0 && r < N && c < N) {
            if (map[r][c] == ' ' || map[r][c] == 'G')
                if (!vstd[r][c]) {
                    vstd[r][c] = true;
                    dfs(r,c,dir + compass[dir1] + " ",vstd);
                }
        }
    }
}

输出:

8
########
  #    #
# # ## #
# #  #G#
#P   ###
#### # #
#G   #G#
########
E E E S S W W W  in:978000 with bfs
E E E S S W W W  in:188100 with dfs

对于这个输入,dfs 在很短的时间内完成。尝试更大的例子。
注意:对于大量输入,它可能会导致 StackOverflowError。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。