Java 最短路径的Floyd-Warshall算法

Java 最短路径的Floyd-Warshall算法,java,floyd-warshall,Java,Floyd Warshall,我翻阅了一些旧的竞赛题,发现了这个,看起来很有趣,我试着使用floyd warshall算法来获得从任何节点到任何其他节点的最短路径,你们能看到我做错了什么吗?它不会给出竞赛问题页面上列出的所需输出 import java.io.*; import java.util.*; public class DistanceBetween { public static void main(String[] args) throws FileNotFoundException { Scan

我翻阅了一些旧的竞赛题,发现了这个,看起来很有趣,我试着使用floyd warshall算法来获得从任何节点到任何其他节点的最短路径,你们能看到我做错了什么吗?它不会给出竞赛问题页面上列出的所需输出

import java.io.*;
import java.util.*;

public class DistanceBetween {


public static void main(String[] args) throws FileNotFoundException {
    Scanner s = new Scanner(new File("DATA5.txt"));
    int n = Integer.parseInt(s.nextLine());
    int[][] dist = new int[60][60];
    for(int y=0;y<60;++y)for(int x=0;x<60;++x)dist[y][x]=10000000;
    Map<Character, Integer> map = new TreeMap<Character, Integer>();
    for (int i = 0; i < n; ++i) {
        String text[] = s.nextLine().split(" ");
        int c = 0;
        if (!map.containsKey(text[0].charAt(0))) {
            map.put(text[0].charAt(0), c);
            c++;
        }
        if (!map.containsKey(text[0].charAt(1))) {
            map.put(text[0].charAt(1), c);
            c++;
        }
        dist[map.get(text[0].charAt(0))][map.get(text[0].charAt(1))] = Integer.parseInt(text[1]);
    }
    for (int k = 0; k < map.size(); ++k) {
        for (int i = 0; i < map.size(); ++i) {
            for (int j = 0; j < map.size(); ++j) {
                dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    for (int i = 0; i < 5; ++i) {
        String text = s.nextLine();
        System.out.println(dist[map.get(text.charAt(0))][map.get(text.charAt(1))]);
    }
}}
import java.io.*;
导入java.util.*;
公共类之间的距离{
公共静态void main(字符串[]args)引发FileNotFoundException{
扫描仪s=新扫描仪(新文件(“DATA5.txt”);
int n=Integer.parseInt(s.nextLine());
int[]dist=新int[60][60];

对于(int y=0;y,代码中存在几个问题:

覆盖映射 您的
int c
for
循环的
局部变量,这意味着使用的最高映射索引无法保存到下一次迭代,因此下一次迭代中的读数将覆盖上一次迭代。因此,数据加载后距离矩阵没有正确填充

解决方案:
int c=0;
for
循环中移出

单向道路 说明中的道路是双向的,但你只将其注册为单向的。因此,城镇之间不存在的连接会更高

解决方案:
dist[map.get(text[0].charAt(1))][map.get(text[0].charAt(0))]=Integer.parseInt(text[1]);
放在类似的后面


除了这些困难的问题,我还有一些提示给你。你不必遵循它们,但如果你想提高你的编程技能,那么你应该考虑它们

乱码 你的代码很难阅读,有多个重述信息,如标记,解决过程是在单一方法中等。这样的代码不仅很难阅读,而且非常难调试修复。为了你自己的利益,我建议你写得更干净

算法效率

Floyd Warshall算法有一个<代码> O(n ^ 3)< /代码>复杂度。问题的大小(城镇的数量)是a- m=13。在这种复杂性下,它使得<代码> 13 ^ 3=2197 < /代码>迭代。我知道,它似乎不太多,但是考虑在给定的时间限制下要解决的任务量。

我建议您使用复杂度
O(|E |+| V | log | V |)V |
。在这个任务中,简化后最糟糕的情况是
| E |=(| V | 2)/2,| V |=13
。这意味着最终的迭代次数是
5(|V | log^ 2/2+| V | log | V |=5(13*2)/2)~ 5×132=660 < /代码>。如果我没有错,并且犯了任何错误,这就少得多,特别是当我们考虑任务总量时。

输入读数
我可能错了,但我参加了多个编程竞赛和竞赛,它从未强迫参加者使用文件。输入总是从文件重定向到标准输入。我想,这主要是出于安全考虑,但简化可能也非常有益。

我得到的问题是,我是明星ting现在想做SPOJ,我不得不承认这以后很难,但我遇到了同样的问题,我也用了Floyd Warshall

    import java.util.*;

    public class Floydwarshall {


public static void main(String[] args) {
    Scanner s = new Scanner(System.in);
    String q = s.nextLine();
    for(int t=0;t<Integer.parseInt(q);++t){
        int n = Integer.parseInt(s.nextLine());
        int[][] cost = new int[n][n];
        for (int y = 0; y < n; ++y) {
            for (int x = 0; x < n; ++x) {
                cost[x][y] = 10000;
            }
        }
        Map<String, Integer> map = new TreeMap<String, Integer>();
        int c = 0;
        for (int i = 0; i < n; ++i) {
            String a = s.nextLine();
            if (!map.containsKey(a)) {
                map.put(a, c);
                c++;
            }
            int f = Integer.parseInt(s.nextLine());
            for (int j = 0; j < f; ++j) {
                String text[] = s.nextLine().split(" ");
                cost[map.get(a)][Integer.parseInt(text[0]) - 1] =
                        cost[Integer.parseInt(text[0]) - 1][map.get(a)] = Integer.parseInt(text[1]);
            }
        }
        for (int k = 0; k < map.size(); ++k) {
            for (int i = 0; i < map.size(); ++i) {
                for (int j = 0; j < map.size(); ++j) {
                    cost[i][j] = Math.min(cost[i][j], cost[i][k] + cost[k][j]);
                }
            }
        }
        int num = Integer.parseInt(s.nextLine());
        for (int i = 0; i < num; ++i) {
            String text[] = s.nextLine().split(" ");
            System.out.println(cost[map.get(text[0])][map.get(text[1])]);
        }
    }
}}
import java.util.*;
公共级浮标{
公共静态void main(字符串[]args){
扫描仪s=新的扫描仪(System.in);
字符串q=s.nextLine();

对于(int t=0;tit没有给出最短路径,即链接上的输出。我认为最好是将结果的特定部分以及与您的问题不同的结果附加到网站上——如果这不是太多的文本的话。我知道我的代码很乱,因为我很快将要进行另一个编程竞赛,所以我我一直在为自己计时并尽快完成代码,只是因为它很凌乱并不意味着它不会工作,而且只有在输出匹配的情况下,评委才会标记你的代码编写得有多好。但是无论如何,感谢你关于如何加快调试速度的建议,无论如何,我还没有学会dijkstra,但我正在努力now@Panphobia是 啊我知道,评委们并不关心代码质量,但根据我自己的经验,你很少会在第一次尝试时编写代码,然后发现错误,因为时间压力,这是一个真正的挑战……无论如何,我发现了你的错误,并使解决方案起作用,所以请随意验证它并接受答案,如果你愿意的话