求矩阵左上角到右下角路径的最大价值

题目是来自某讯2016实习生移动客户端开发笔试的一道编程题,如下:

给出一M*N的矩阵,每个格子中都有一个非负整数,只能向右或向下移动,求从左上角到右下角的所有路径中的最大值(每条路径的值为对路径中所进过的格子中的数求和)。

输入格式:

4 5

1 0 0 8 0

0 0 3 0 0

4 0 0 5 0

0 6 0 0 0

之前没怎么接触过动态规划,我自己在实现的时候最先想到的是基于广度优先的思想,效率不高,写起来也麻烦,既然实现了也不怕笑话,我这里贴出来:

import java.util.Scanner;
import java.util.Queue;
import java.util.LinkedList;

public class PreciousMatrix {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int M = scanner.nextInt();
        int N = scanner.nextInt();
        scanner.nextLine();
        int matrix[][] = new int[M + 1][N + 1];
        for (int i = 1; i < M + 1; i++) {
            for (int j = 1; j < N + 1; j++) {
                matrix[i][j] = scanner.nextInt();
            }
            scanner.nextLine();
        }
        Queue que = new LinkedList<>();
        int book[][] = new int[M + 1][N + 1];
        int next[][] = {{0, 1}, {1, 0}};
        int tx, ty;
        int flag;
        Position firstPos = new Position(1, 1, matrix[1][1]);
        que.offer(firstPos);
        Position headPos = null;
        int maxVal = firstPos.val;
        while((headPos = que.poll()) != null) {
            for (int k = 0; k < 2; k++) {
                tx = headPos.x + next[k][0];
                ty = headPos.y + next[k][1];
                if (tx < 1 || tx > M || ty < 1 || ty > N) {
                    continue;
                }
                if (book[tx][ty] == 0) {
                    Position pos = new Position(tx, ty, headPos.val + matrix[tx][ty]);
                    que.offer(pos);
                    book[tx][ty] = 1;
                } else {
                    for (Position p : que) {
                        if (p.x == tx && p.y == ty && p.val < headPos.val + matrix[tx][ty]) {
                            p.val =  headPos.val + matrix[tx][ty];
                        }
                    }
                }
                Position tempPos = que.peek();
                if (tempPos.x == M && tempPos.y == N) {
                    if (maxVal < tempPos.val) maxVal = tempPos.val;
                }
            }
        }
        System.out.println(maxVal);
    }

    static class Position {
        public int x;//当前节点的x
        public int y;//当前节点的y
        public int val;//到当前节点找到的最大值
        public Position(int x, int y, int val) {
            this.x = x;
            this.y = y;
            this.val = val;
        }
    }
}

这种方法没有记录求出最大val的路线,可以用一个数组保存每次poll出来的头结点的元素(保存引用防止gc),在Position中定义一个父节点引用,并使用一个变量保存val最大的Position,然后依次遍历其父节点得出路径。

后来才知道这道题原来和LeetCode上64. Minimum Path Sum这道题是一样的,网上很多解题思路是基于动态规划的,这里我结合自己的理解,也敲一遍,做个记录。

public static void maxPathSum(int m, int n, int arr[][]) {
        for (int i = 2; i <= n; i++) {
            arr[1][i] += arr[1][i - 1];
        }
        for (int j = 2; j <= m; j++) {
            arr[j][1] += arr[j - 1][1];
        }
        for (int i = 2; i <= m; i++ ) {
            for (int j = 2; j <= n; j++) {
                arr[i][j] += max(arr[i - 1][j], arr[i][j -1]);
            }
        }
        System.out.println(arr[m][n]);
    }

    public static int max(int val1, int val2) {
        if (val1 > val2) return val1;
        return val2;
    }


动态规划效率高多了,而且思路清晰实现的代码的很简洁!




你可能感兴趣的:(Coding,Practice)