oj acm 1026 廣度搜索

最短距離求解

求解最短距離,使用廣度優先搜索和優先隊列結合

使用visted數組記錄是該層某節點否訪問過。由於是保存在優先隊列中,只要該層前面的路徑有訪問該節點,則一定是到達該節點的最短距離。

使用flag數組記錄從某節點到達x,y的方向,從而輸出時能還原路徑。

代碼

import java.io.File;
import java.io.FileNotFoundException;
import java.util.PriorityQueue;
import java.util.Scanner;

//廣度優先
class Pos implements Comparable {
    private int x;
    private int y;
    private int step;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getStep() {
        return step;
    }

    public void setStep(int step) {
        this.step = step;
    }

    @Override
    public String toString() {
        return "Pos{" +
                "x=" + x +
                ", y=" + y +
                ", step=" + step +
                '}';
    }

    public Pos(int x, int y, int step) {
        this.x = x;
        this.y = y;
        this.step = step;
    }

    public Pos() {
    }

    @Override
    public int compareTo(Object o) {
        //從小到大
        if (o instanceof Pos) {
            Pos p = (Pos) o;
            return this.step - p.step;
        }
        return 0;
    }
}

public class Main_1026 {
    private static int[][] dir = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    private static int n, m;
    private static int count;
    private static PriorityQueue<Pos> result;
    private static int[][] flag;
    private static boolean[][] visited;
    private static char[][] c;

    public static void main(String[] args) throws FileNotFoundException {
        Scanner in = new Scanner(new File("src/input.txt"));
        while (in.hasNext()) {
            n = in.nextInt();
            m = in.nextInt();
            count = 0;
            result = new PriorityQueue<>();
            flag = new int[n][m];
            visited = new boolean[n][m];
            c = new char[n][m];
            for (int i = 0; i < n; i++) {
                String s = in.next();
                for (int j = 0; j < m; j++) {
                    c[i][j] = s.charAt(j);
                }
            }
            int step = c[0][0]=='.'? 0 : c[0][0] -'0';
            result.add(new Pos(0, 0, step));
            visited[0][0]= true;
            int count = bfs();
            if(count != -1) {
                System.out.println("It takes "+count+
                        " seconds to reach the target position, let me show you the way.");
                print(n-1,m-1);
            }else{
                System.out.println("God please help our poor hero.");
            }
            System.out.println("FINISH");
        }
    }

    public static int bfs() {
        while (!result.isEmpty()) {
            Pos pre = result.poll();
            if (pre.getX() == n - 1 && pre.getY() == m - 1) {
                return pre.getStep();
            }
            for (int i = 0; i < 4; i++) {
                int x = pre.getX() + dir[i][0];
                int y = pre.getY() + dir[i][1];
                if (isValid(x, y)) {
                    int step = c[x][y]=='.'? 1: c[x][y]-'0'+1;
                    Pos next = new Pos(x, y, pre.getStep()+step);
                    visited[x][y] = true;
                    flag[x][y] = i + 1;
                    result.add(next);
                }
            }
        }
        return -1;
    }

    public static void print(int x, int y) {
        if (flag[x][y] == 0) {
            if(c[x][y] !='.'){
                while(c[x][y]-'0'>=1){
                    count++;
                    c[x][y]--;
                    System.out.printf("%ds:FIGHT AT (%d,%d)\n", count, x, y);
                }
            }
            return;
        }
        int pre_x = x - dir[flag[x][y] - 1][0];
        int pre_y = y - dir[flag[x][y] - 1][1];
        print(pre_x, pre_y);
        count++;
        System.out.printf("%ds:(%d,%d)->(%d,%d)\n", count, pre_x, pre_y, x, y);
        while (c[x][y] != '.' && c[x][y] - '0' >= 1) {
            count++;
            c[x][y]--;
            System.out.printf("%ds:FIGHT AT (%d,%d)\n", count, x, y);
        }

    }

    public static boolean isValid(int x, int y) {
        if (x < 0 || x >= n || y < 0 || y >= m) {
            return false;
        }
        if (c[x][y] == 'X') {
            return false;
        }
        if(visited[x][y]){
            return false;
        }
        return true;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章