1. 程式人生 > >仙島求藥(經典的BFS和DFS運用題)

仙島求藥(經典的BFS和DFS運用題)

原題目來自OpenJudge
下面的都是Java實現的
先看看思路比較簡單的BFS


import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class Noi2727 {

    private static char[][] coordinate;

    private static int[][] minCoordinate;

    private static int ans = 0;
    
    // 地圖的縱向長度
private static int n; // 地圖的橫向長度 private static int m; // 仙草的縱座標 private static int q; // 仙草的橫座標 private static int p; public static class Index { public int x; public int y; public Index(int x, int y) { this.x = x; this.
y = y; } } public static void bfs(Index index) { LinkedList<Index> queue = new LinkedList<>(); queue.offer(index); while(!queue.isEmpty()) { Index temp = queue.poll(); int i = temp.x; int j = temp.y; // 如果是障礙物
if(coordinate[i][j] == '#') { continue; } // 如果是仙草,找到就跳出。因為是BFS所以第一個解就是最優解了 if(coordinate[i][j] == '*') { ans = minCoordinate[i][j]; break; } // 往上走,不超過界線 && 沒訪問過該點 if(i > 0 && minCoordinate[i - 1][j] == Integer.MAX_VALUE) { // 該點對應的minCoordinate的值設定為起點即@的位置到該點的最短距離 minCoordinate[i - 1][j] = minCoordinate[i][j] + 1; queue.offer(new Index(i - 1, j)); } // 往下走 if(i < n - 1 && minCoordinate[i + 1][j] == Integer.MAX_VALUE) { minCoordinate[i + 1][j] = minCoordinate[i][j] + 1; queue.offer(new Index(i + 1, j)); } // 往左走 if(j > 0 && minCoordinate[i][j - 1] == Integer.MAX_VALUE) { minCoordinate[i][j - 1] = minCoordinate[i][j] + 1; queue.offer(new Index(i, j - 1)); } // 往右走 if(j < m - 1 && minCoordinate[i][j + 1] == Integer.MAX_VALUE) { minCoordinate[i][j + 1] = minCoordinate[i][j] + 1; queue.offer(new Index(i, j + 1)); } } } public static void main(String[] args) { List<Integer> list = new ArrayList<>(); Scanner scanner = new Scanner(System.in); while(true) { n = scanner.nextInt(); m = scanner.nextInt(); if(n == 0 && m == 0) { break; } coordinate = new char[n][m]; minCoordinate = new int[n][m]; int x = 0, y = 0; for(int i = 0; i < n; i++) { String temp = scanner.next(); for(int j = 0; j < m; j++) { coordinate[i][j] = temp.charAt(j); // 沒訪問的點都設位置為Integer.MAX_VALUE minCoordinate[i][j] = Integer.MAX_VALUE; if(coordinate[i][j] == '@') { x = i; y = j; } else if(coordinate[i][j] == '*') { q = i; p = j; } } } // 起點到起點為0 minCoordinate[x][y] = 0; bfs(new Index(x, y)); if(ans == 0) { list.add(-1); } else { list.add(ans); } ans = 0; } for(Integer i : list) { System.out.println(i); } } }

接下來是DFS實現

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class Main {

    private static char[][] coordinate;

    private static int[][] minCoordinate;

    private static int ans = 0;

    // 地圖的縱向長度
    private static int n;

    // 地圖的橫向長度
    private static int m;

    // 仙草的縱座標
    private static int q;

    // 仙草的橫座標
    private static int p;

    public static void dfs(int i, int j) {
        int step = minCoordinate[i][j];
        // 如果是仙草
        if(coordinate[i][j] == '*') {
            ans = step;
        }
        step++;
        // 不超界限 && 不是怪物 && 更優
        if(i > 0 && coordinate[i - 1][j] != '#' && minCoordinate[i - 1][j] > step) {
            minCoordinate[i - 1][j] = step;
            dfs(i - 1, j);
        }
        if(i < n - 1 && coordinate[i + 1][j] != '#' && minCoordinate[i + 1][j] > step) {
            minCoordinate[i + 1][j] = step;
            dfs(i + 1, j);
        }
        if(j > 0 && coordinate[i][j - 1] != '#' && minCoordinate[i][j - 1] > step) {
            minCoordinate[i][j - 1] = step;
            dfs(i, j - 1);
        }
        if(j < m - 1 && coordinate[i][j + 1] != '#' && minCoordinate[i][j + 1] > step) {
            minCoordinate[i][j + 1] = step;
            dfs(i, j + 1);
        }
    }

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        while(true) {
            n = scanner.nextInt();
            m = scanner.nextInt();
            if(n == 0 && m == 0) {
                break;
            }
            coordinate = new char[n][m];
            minCoordinate = new int[n][m];
            int x = 0, y = 0;
            for(int i = 0; i < n; i++) {
                String temp = scanner.next();
                for(int j = 0; j < m; j++) {
                    coordinate[i][j] = temp.charAt(j);
                    // 沒訪問的點都設位置為Integer.MAX_VALUE
                    minCoordinate[i][j] = Integer.MAX_VALUE;
                    if(coordinate[i][j] == '@') {
                        x = i;
                        y = j;
                    } else if(coordinate[i][j] == '*') {
                        q = i;
                        p = j;
                    }
                }
            }
            // 起點到起點為0
            minCoordinate[x][y] = 0;
            dfs(x, y);
            if(ans == 0) {
                list.add(-1);
            } else {
                list.add(ans);
            }
            ans = 0;
        }
        for(Integer i : list) {
            System.out.println(i);
        }
    }
}