- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我在 SO 上查看了与此相关的其他帖子。
我试图找到图中节点之间的最短路径。节点之间的每条边都有一个 (X, Y)
坐标。
我想计算从 Node I
到 Node J
的最短距离。一旦有了,我想从最短路径的坐标中将所有 X 值和 Y 值相加。
我已经坚持了几个小时,希望能有一些见解。
代码如下:
class Vertex implements Comparable<Vertex> {
private int id;
private List<Edge> adjacencyList;
private Vertex previousVertex;
private double minDistance;
private Coordinate point;
public Vertex(int id, Coordinate point) {
this.id = id;
this.point = point;
this.adjacencyList = new ArrayList<>();
}
public int getID() {
return this.id;
}
public Coordinate getPoint() {
return this.point;
}
public List<Edge> getAdjacencyList() {
return this.adjacencyList;
}
public void addNeighbour(Edge edge) {
this.adjacencyList.add(edge);
}
public Vertex getPreviousVertex() {
return this.previousVertex;
}
public void setPreviousVertex(Vertex previousVertex) {
this.previousVertex = previousVertex;
}
public double getMinDistance() {
return this.minDistance;
}
public void setMinDistance(double minDistance) {
this.minDistance = minDistance;
}
public int compareTo(Vertex other) {
return Double.compare(this.minDistance, other.minDistance);
}
}
class Edge {
private double weight;
private Vertex targetVertex;
public Edge(double weight, Vertex targetVertex) {
this.weight = weight;
this.targetVertex = targetVertex;
}
public double getWeight() {
return this.weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public Vertex getTargetVertex() {
return this.targetVertex;
}
public void setTargetVertex(Vertex targetVertex) {
this.targetVertex = targetVertex;
}
}
class Algorithm {
public void shortestPath(Vertex startVertex) {
startVertex.setMinDistance(0);
PriorityQueue<Vertex> queue = new PriorityQueue<>();
queue.add(startVertex);
while (!queue.isEmpty()) {
Vertex actualVertex = queue.poll();
for (Edge edge : actualVertex.getAdjacencyList()) {
Vertex v = edge.getTargetVertex();
double weight = edge.getWeight();
double currentDistance = actualVertex.getMinDistance() + weight;
if (currentDistance < v.getMinDistance()) {
queue.remove(v);
v.setMinDistance(currentDistance);
v.setPreviousVertex(actualVertex);
queue.add(v);
}
}
}
}
public List<Vertex> getShortestPathTo(Vertex targetVertex){
List<Vertex> path = new ArrayList<Vertex>();
for (Vertex vertex = targetVertex; vertex != null; vertex = vertex.getPreviousVertex()){
path.add(vertex);
}
Collections.reverse(path);
return path;
}
}
class Coordinate {
private int x;
private int y;
Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public static Coordinate readInput(Scanner in) {
String[] temp = in.nextLine().split(" ");
return new Coordinate(Integer.parseInt(temp[0]), Integer.parseInt(temp[1]));
}
}
如果我从这个文本文件中读取
3 //# of coordinates
0 0 // (x, y)
1 1 // (x, y)
2 0 // (x, y)
1 2 //edge between coordinate 1 to 2
2 3 //edge between coordinate 2 to 3
我的测试用例看起来像这样:
class Test {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String[] constants = s.nextLine().split(" ");
final int N = Integer.parseInt(constants[0]);
List<Coordinate> junctions = new ArrayList<>();
List<Coordinate> paths = new ArrayList<>();
List<Vertex> vertices = new ArrayList<>();
for(int i = 0; i < N; i++) {
junctions.add(Coordinate.readInput(s));
}
for(int i = 0; i < N-1; i++) {
paths.add(Coordinate.readInput(s));
}
for(int i = 0; i < N-1; i++) {
int x = junctions.get(paths.get(i).getX() - 1).getX();
int x1 = junctions.get(paths.get(i).getY() - 1).getX();
int y = junctions.get(paths.get(i).getX() - 1).getY();
int y1 = junctions.get(paths.get(i).getY() - 1).getY();
Vertex vertex1 = new Vertex(paths.get(i).getX(), new Coordinate(x, y));
Vertex vertex2 = new Vertex(paths.get(i).getY(), new Coordinate(x1, y1));
double distance = Math.sqrt(Math.pow(x - x1, 2) + Math.pow(y - y1, 2));
vertex1.addNeighbour(new Edge(distance, vertex2));
vertices.add(vertex1);
vertices.add(vertex2);
}
Algorithm a = new Algorithm();
int x = 0;
int y = 0;
for(int i = 0; i < vertices.size(); i++) {
a.shortestPath(vertices.get(i));
for(Vertex vertex : a.getShortestPathTo(vertices.get(i+1))) {
x += vertices.get(vertex.getID()).getPoint().getX();
y += vertices.get(vertex.getID()).getPoint().getY();
}
}
//This prints out "Total X: 5 Total Y: 3" (should be 3 and 1)
System.out.println("Total X: " + x + " Total Y: " + y);
}
}
最佳答案
您的问题出在这部分:
public void shortestPath(Vertex startVertex) {
startVertex.setMinDistance(0);
PriorityQueue<Vertex> queue = new PriorityQueue<>();
queue.add(startVertex);
//The rest is omitted
}
每次运行 shortestPath
方法时,您应该将所有顶点中的所有 minDistance
重置为无穷大,而不仅仅是 startVertex
。
对于除startVertex
之外的所有顶点,开头的minDistance
应该设置为无穷大(或Double.MAX_VALUE
),或者它将始终为 0
。
代码:
for(Vertex v : vertices){
v.setMinDistance(Double.MAX_VALUE);
v.setPreviousVertex(null);
}
a.shortestPath(vertices.get(i));
此外,在 Test
类的第三个循环中,您多次初始化相同的顶点。所以,你应该做的是,预初始化所有顶点并将它们保存在一个数组中,如下所示:
for(int i = 0; i < N; i++){
vertices.add(new Vertex(i + 1, junctions.get(i));
}
for(int i = 0; i < N - 1; i++){
//Initialize x, y, x1, y1 here, I just skipped it
Vertex vertex1 = vertices.get(paths.getX() - 1);
Vertex vertex2 = vertices.get(paths.getY() - 1);
double distance = Math.sqrt(Math.pow(x - x1, 2) + Math.pow(y - y1, 2));
vertex1.addNeighbour(new Edge(distance, vertex2));
}
关于java - 用Dijkstra算法求距离为坐标的最短路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29680904/
这个问题在这里已经有了答案: Integer summing blues, short += short problem (5 个答案) 关闭 7 年前。 版本:Visual Studio Prof
我尝试执行以下代码: public class Test5 { /** * @param args */ public static void main(String[] args) {
这是我的任务,我尝试仅使用简短的 if 语句来完成此任务,我得到的唯一错误是使用“(0.5<=ratio<2 )”,除此之外,构造正确吗? Scanner scn = new Scanner(
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我有一个简单的类型 data Day = Monday | Tuesday | Wednesday | Thursday | Friday 我是haskell的新手,所以我写==如下。 (==) :
如何实现“简短”和“详细”两个按钮? “短”应该是默认值,并显示页面的一个版本。单击“详细”按钮后,应显示该页面的另一个版本。 由于这有点难以解释,或许可以看下面的例子。 示例页面: 别管内容 需要j
有没有一种方法可以在 C# 中执行此操作,而无需为现有的每个 var 类型创建一个新方法来重载? $box = !empty($toy) : $toy ? ""; 我能想到的唯一方法是: if (t
我想使用 setInterval 创建一个节拍器。我希望能够达到 300 bpm 这样的高 bpm。即使文件足够短,可以根据需要播放多次,它也很容易 打嗝。此外,许多浏览器都存在短音频文件的问题——S
我们现在有一个正在生产中的应用程序,它会将 IAP 收据发送到我们的服务器,这些收据显然太短,而且我们的服务器没有经过 apple 的验证。 Apple 正确验证的长收据长度为 3192。短收据长度均
例如,许多软件使用的许可证 key 。我曾想过对一个序列进行密码签名,所以我可能有 4 个字节用于 ID,8 个字节用于签名,但我找不到合适的算法。 我需要的是攻击者无法轻易生成,但存储在大约 20
作为一个学生项目,我们正在构建一个机器人,它应该跑完规定的路线并捡起一个木制立方体。它的核心是一台运行 debian 的单板计算机,配备 ARM9,频率为 250MHz。因此 Controller 的
在将 short 转换为字节数组时,我在网上找到了以下解决方案,但不太理解所涉及的逻辑。 //buffer is an array of bytes, bytes[] buffer[position]
如何在 PHP namespace 环境中检查对象的类而不指定完整的命名空间类。 例如,假设我有一个对象库/实体/契约(Contract)/名称。 以下代码不起作用,因为 get_class 返回完整
我有一个 View 范围的托管 bean,其托管属性绑定(bind)到查询字符串参数。 JSF 给了我熟悉的异常: javax.faces.FacesException: Property reset
根据 this post我已经修复了对象检查器。有时代码可以很好地运行 10 个条目,使它们全部正确,有时它可以运行 5 个条目。有时它会导致条目错误。 在获取元素的内部文本时总是会失败。当它的 Y/
我正在编写一组工具,其中 C++ 应用程序使用 AES 加密标准对数据进行编码,而 Java 应用程序对其进行解码。据我所知, key 长度必须为 16 个字节。但是当我尝试使用不同长度的密码时,我遇
我有以下代码: short num_short = 1; int possible_new_short = 1; valid = 1; while (valid) { poss
因此,作为 C 的新手,我遇到了我的第一个 SIGSEGV 错误。它出现在一个简短的 C 程序中,该程序旨在成为“猜数字”游戏。它由一个比较两个数字的自定义函数和一个带有输入的 do-while 循环
我不是严格意义上的初级程序员,但我没有接受过数学以外的正规教育 - 所以这纯粹是业余爱好,可能是业余的。 我最近自己开发了一个算法来解决这个问题,但我想知道是否有任何相对简单的算法明显更高效/更快?
我正在使用短条件来区分记录列表中显示的值。 例如,如果我希望强调 ( ) 标识符大于 100 的客户的姓名,请执行以下操作: {# Displays the identifier of the c
我是一名优秀的程序员,十分优秀!