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

允许向左、向右、底部和向上移动的最小成本路径

如何解决允许向左、向右、底部和向上移动的最小成本路径

问题说明:
给定一个大小为 N 的方形网格,其中每个单元格包含整数成本,表示遍历该单元格的成本,我们需要找到从左上角单元格到右下角单元格的路径,由此产生的总成本为最低限度。 从单元格 (i,j) 我们可以去 (i,j-1)(i,j+1)(i-1,j)(i+1,j)

注意:假设输入矩阵中不存在负成本周期。

下面是我写的代码

class Coordinate {
    int x;
    int y;

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

    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;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Coordinate other = (Coordinate) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }

}

public class MinCostPath {

    public static int minimumCostPath(int[][] grid) {
        int R = grid.length;
        int C = grid[0].length;
        int[][] dist = new int[R][C];
        for (int i = 0; i < R; i++) {
            for (int j = 0; j < C; j++) {
                dist[i][j] = Integer.MAX_VALUE;
            }
        }
        dist[0][0] = grid[0][0];
        Queue<Coordinate> q = new LinkedList<>();

        q.add(new Coordinate(0,0));
        int[] x = { -1,1,0 };
        int[] y = { 0,-1 };
        while (!q.isEmpty()) {
            Coordinate current = q.poll();
            for (int i = 0; i < 4; i++) {
                int xi = current.getX() + x[i];
                int yi = current.getY() + y[i];

                if (isSafe(xi,yi,R,C)) {
                    if (dist[xi][yi] > dist[current.getX()][current.getY()] + grid[xi][yi]) {
                        dist[xi][yi] = dist[current.getX()][current.getY()] + grid[xi][yi];
                        Coordinate c = new Coordinate(xi,yi);
                        if (!q.contains(c))
                            q.add(c);
                    }

                }
            }

        }

        return dist[R - 1][C - 1];
    }

    private static boolean isSafe(int xi,int yi,int r,int c) {
        return (xi >= 0) && (xi < r) && (yi >= 0) && (yi < c);
    }

    public static void main(String[] args) {
        int[][] grid = { { 9,4,9,9 },{ 6,7,6,4 },{ 8,3,7 },{ 7,10 } };
        System.out.println(minimumCostPath(grid));

    }

}

它给出了“运行时错误:超出时间限制”错误

下面是 geeksforgeeks 的一篇文章,其中有解决方案。 Minimum Cost Path Problem

我无法理解的是,为什么我的代码文章中提到的解决方案有效时出现“超出时间限制”错误。据我了解,这两种解决方案都在做完全相同的事情。

请帮助我理解我编写的代码中的差异以及需要进行哪些优化。提前致谢。

解决方法

代码中需要什么优化

需要重新表述问题,以便您可以应用 Dijkstra 算法 (https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)

该算法假设链接是有成本的,而不是节点(单元)。考虑具有遍历成本 c 和 d 的两个相邻单元格。从第一个到第二个旅行会增加成本 d.从第二个到第一个旅行会增加成本 c。因此,您可以使用成本为 c 和 d 的两个单向链路连接两个单元格。 Dijkstra 算法会在整个路径经过时为您提供正确的成本,减去第一个单元的遍历成本 - 这是一个常数,因此在找到最佳路径时可以忽略。

我使用 Dijkstra 的 boost 图实现,它快速且经过良好测试 ( https://www.boost.org/doc/libs/1_76_0/libs/graph/doc/dijkstra_shortest_paths.html )。如果您以前没有使用过 boost 库,那么 API 是一个挑战,所以我使用 C++ 风格的包装器来简化编码 (https://github.com/JamesBremner/PathFinder)

这是路径查找器关于您发布的示例问题的输出

C:\Users\James\code\PathFinder\bin>mazes ..\dat\vivekkumar.txt
Mazes
cellcosts
s9 4 9 9
6 7 6 4
8 3 3 7
7 4 9 e10
4 by 4

0 -> 1 -> 5 -> 9 -> 10 -> 11 -> 15 ->

+---+---+---+---+
| s   *         |
+   +   +   +   +
|     *         |
+   +   +   +   +
|     *   *   * |
+   +   +   +   +
|             e |
+---+---+---+---+
,

从您的实施来看,您似乎正在尝试使用广度优先搜索而不是 Dijkstra,这是解决此问题的正确方法。

您需要使用优先队列和地图来跟踪您的路径。

同样对于 BFS,您通常不需要执行实际上不必要地消耗时间的 if (! q.contains(node))

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