記憶力搜索

題目:在數字矩陣中,從左上角到右下角,每次只能向右或向下,如何規劃路徑,能獲得最大數字總和?
思路1:使用貪心,每次都選取矩陣中最大的值,進行前進,但是這種方法得到的不是最優解,可能出現因小失去的情況
思路2:使用搜索算法
廣度優先算法求解最優解
深度優先算法求解全部解
這裏求全部解,並獲取最大值,所用用深度優先算法
如何提高效率呢?
算法的優化其實就是減少不必要的計算
可以使用記憶力搜索,這樣可以減少不必要的計算。就是記錄把搜索過的一些信息給記錄下來。
這道題中用best(i,j)表示當前路徑的最大和,然後如果每搜到一個點,都可以和這個數比較,如果比它大,就更新這個數,繼續搜,如果比它小,就不搜了,直接剪枝。

public class DeepFirstSearch {

    // 定義best(i,j) 和 M N
    private int[][] best = null;
    private int M = 0;
    private int N = 0;

    // 定義方向常量
    private static final int RIGHT = 1;
    private static final int DOWN = 2;
    // 當前搜索的方向數組
    private List<Integer> curPath = null;
    // 記錄最大值對應的方向數組
    private Integer[] bestPath = null;

    // 當前搜索點
    private int curX = 0;
    private int curY = 0;
    // 當前搜索累計值
    private int value = 0;
    // 記錄搜索到的最大值
    private int maxValue = 0;

    // 往某個方向前進
    private void goDir(int dir, int[][] matrix) {
        // 前進
        if(dir == DOWN) {
            curX++;
            value += matrix[curX][curY];
        } else if(dir == RIGHT) {
            curY++;
            value += matrix[curX][curY];
        }
        // 記錄方向
        curPath.add(dir);
    }

    // 往某個方向回退
    private void goBackDir(int dir, int[][] matrix) {
        // 回退
        if(dir == DOWN) {
            value -= matrix[curX][curY];
            curX--;
        } else if(dir == RIGHT) {
            value -= matrix[curX][curY];
            curY--;
        }
        // 移除方向
        curPath.remove(curPath.size() - 1);
    }

    // 深搜
    private void search(int dir, int[][] matrix) {
        // 往某方向前進
        goDir(dir, matrix);
        // 到達終點
        if(curX == M - 1 && curY == N - 1) {
            if(value > maxValue) {
                // 記錄最大值和路徑
                maxValue = value;
                bestPath = new Integer[curPath.size()];
                curPath.toArray(bestPath);
            }
        } else if(value <= best[curX][curY]) {
            // 不搜索了,等着goBack,剪枝
        } else {
            // 更新best(i,j),記憶
            best[curX][curY] = value;
            // 朝下一個方向搜索
            if(curX < M - 1) {
                search(DOWN, matrix);
            }
            if(curY < N - 1) {
                search(RIGHT, matrix);
            }
        }
        // 往某方向回退
        goBackDir(dir, matrix);
    }

    // 獲取最大值
    public int getMaxAward(int[][] matrix) {
        // 初始化
        value = matrix[0][0];
        M = matrix.length;
        N = matrix[0].length;
        best = new int[M][N];
        curPath = new ArrayList<Integer>();
        // 開始搜索
        if(M > 1) {
            search(DOWN, matrix);
        }
        if(N > 1) {
            search(RIGHT, matrix);
        }
        // 最大值
        return maxValue;
    }

    // 打印最佳路徑
    public void printBestPath() {
        // 打印路徑
        for(int i = 0; i < bestPath.length; i++) {
            if(bestPath[i] == RIGHT) {
                System.out.print("右 ");
            } else {
                System.out.print("下 ");
            }
        }
        System.out.println();
    }

}
Main.java:

/**
 * @author xiaoshi on 2018/10/20.
 */
public class Main {

    public static void main(String[] args) {

        int[][] matrix1 = {
            {300, 500, 560, 400, 160},
            {1000, 100, 200, 340, 690},
            {600, 500, 500, 460, 320},
            {300, 400, 250, 210, 760}
        };

        int[][] matrix2 = {
            {300, 500, 2560, 400},
            {1000, 100, 200, 340},
            {600, 500, 500, 460},
            {300, 400, 250, 210},
            {860, 690, 320, 760}
        };

        DeepFirstSearch dp = new DeepFirstSearch();

        System.out.println(dp.getMaxAward(matrix1));
        dp.printBestPath();

        System.out.println(dp.getMaxAward(matrix2));
        dp.printBestPath();

    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章