如何解决允许向左、向右、底部和向上移动的最小成本路径
问题说明:
给定一个大小为 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 举报,一经查实,本站将立刻删除。