图论 :二维矩阵最小路径

package day7;
/**
 * Write by Bloomberg
 * 0500051545
 * 0128054984
 * 0029041651
 * 6874014654
 * 3213013584
 * 1651050001
 * 6549010406
 * 1546040500
 * 5198010511
 * 6545000891
 */

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Dijkstra {
    private int[][] map; // 地图结构保存
    private int[][] edges; // 邻接矩阵
    private int[] prev; // 前驱节点标号
    private boolean[] s; // S集合中存放到起点已经算出最短路径的点
    private int[] dist; // dist[i]表示起点到第i个节点的最短路径
    private int PoiNum; // 点的个数
    private Map<Integer, Poi> indexPoiMap; // 标号和点的对应关系
    private Map<Poi, Integer> PoiIndexMap; // 点和标号的对应关系
    private int v0; // 起点标号
    private Poi startPoi; // 起点
    private Poi endPoi; // 终点
    private Map<Poi, Poi> PoiPoiMap; // 保存点和权重的映射关系
    private List<Poi> allPois; // 保存所有点
    private int maxX; // x坐标的最大值
    private int maxY; // y坐标的最大值

    public static void main(String[] args) throws IOException {
        String filename = "C:\\Users\\Administrator\\Desktop\\test.txt";
        ArrayList out = tes01.out(filename);
        ArrayList<char[]> chars = format1(out);
        int[][] map = format2(chars);
//        for (int i = 0; i < map.length; i++) {
//            for (int j = 0; j < map.length; j++) {
//                System.out.print(map[i][j] + " ");
//            }
//            System.out.println();
//        }
        Poi startPoi = new Poi(0, 0); // 起点
        Poi endPoi = new Poi(9, 9); // 终点

//        int[][] map = DijkstraReader(filename);
//        System.out.println(map);
        Dijkstra dijkstra = new Dijkstra(map, startPoi, endPoi);
        int sum = dijkstra.printShortestPath(map);
        sum = sum + map[0][0];
        System.out.println(sum);
//        int q=0;
//        for (int i = 0; i < path.size(); i++) {
            System.out.print(path.get(i)+"");
//            q+=path.get(i);
//        }
//        System.out.println(q);
//        Iterator<Integer> iterator = path.iterator();
//        while (iterator.hasNext()){
//            System.out.println(iterator.next());}
    }

    public static int[][] format2(ArrayList<char[]> out1) {
        int[][] formap = new int[out1.size()][out1.size()];
        for (int i = 0; i < out1.size(); i++) {
            for (int j = 0; j < out1.size(); j++) {
                char[] charsouti = out1.get(i);
                String s = String.valueOf(charsouti[j]);
                int parseInt = Integer.parseInt(s);
                formap[i][j] = parseInt;
            }
        }
        return formap;
    }

    public static ArrayList<char[]> format1(ArrayList<String> out) {
        ArrayList<char[]> charList = new ArrayList<>();
        for (int i = 0; i < out.size(); i++) {
            char[] chars = out.get(i).toCharArray();
            charList.add(chars);
        }
        return charList;
    }

    public static ArrayList out(String filename) throws IOException {

        try {
            FileInputStream fin = new FileInputStream(filename);
            InputStreamReader reader = new InputStreamReader(fin);
            BufferedReader buffReader = new BufferedReader(reader);
            String m;
            StringBuilder sb = new StringBuilder();
            ArrayList<String> arrayList = new ArrayList<>();
            int[][] formtemp = null;
            int[] filecon = null;

            while ((m = buffReader.readLine()) != null) {
                arrayList.add(m);
            }

            return arrayList;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
//    public static int[][] DijkstraReader(String filename) {
//
//        int[] filecon = null;
//        String m = "";
//        int[][] formtemp = null;
//        BufferedReader file = null;
//        try {
//            file = new BufferedReader(new FileReader(filename));
//            int x =  file.readLine().length();
//            while ((m = file.readLine()) != null) {
//
//                if (!m.equals("")) {
//                    int j = 0;
//                    for (int i = 0; i <x; i++) {
//                        while ((m.substring(0, 1)) != null) {
//                            String s0 = m.substring(0, 1);
//                            int anInt = Integer.parseInt(s0);
//                            String s1 = new StringBuffer(m).delete(0, 1).toString();
//                            m = s1;
//                            filecon[j++] = anInt;
//                        }
//                        int j1 = 0;
//                        formtemp[i][j1++] = filecon[j1++];
//                    }
//                }
//            }
//            file.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//
//        return formtemp;
//    }

    public Dijkstra(int map[][], Poi startPoi, Poi endPoi) {
        this.maxX = map.length;
        this.maxY = map[0].length;
        this.PoiNum = maxX * maxY;
        this.map = map;
        this.startPoi = startPoi;
        this.endPoi = endPoi;
        init();
        dijkstra();
    }

    /**
     * 打印指定起点到终点的最短路径
     */
    public int printShortestPath(int[][] map) {
        int sum = printDijkstra(PoiIndexMap.get(endPoi), map);
        return sum;
    }

    /**
     * 初始化dijkstra
     */
    private void init() {
        // 初始化所有变量
        edges = new int[PoiNum][PoiNum];
        prev = new int[PoiNum];
        s = new boolean[PoiNum];
        dist = new int[PoiNum];
        indexPoiMap = new HashMap<>();
        PoiIndexMap = new HashMap<>();
        PoiPoiMap = new HashMap<>();
        allPois = new ArrayList<>();

        // 将map二维数组中的所有点转换成自己的结构
        int count = 0;
        for (int x = 0; x < maxX; ++x) {
            for (int y = 0; y < maxY; ++y) {
                indexPoiMap.put(count, new Poi(x, y));
                PoiIndexMap.put(new Poi(x, y), count);
                count++;
                allPois.add(new Poi(x, y));
                PoiPoiMap.put(new Poi(x, y), new Poi(x, y, map[x][y]));
            }
        }

        // 初始化邻接矩阵
        for (int i = 0; i < PoiNum; ++i) {
            for (int j = 0; j < PoiNum; ++j) {
                if (i == j) {
                    edges[i][j] = 0;
                } else {
                    edges[i][j] = 9999;
                }
            }
        }

        // 根据map上的权重初始化edges,当然这种算法是没有单独加起点的权重的
        for (Poi Poi : allPois) {
            for (Poi aroPoi : getaroPois(Poi)) {
                edges[PoiIndexMap.get(Poi)][PoiIndexMap.get(aroPoi)] = aroPoi.getValue();
            }
        }

        v0 = PoiIndexMap.get(startPoi);

        for (int i = 0; i < PoiNum; ++i) {
            dist[i] = edges[v0][i];
            if (dist[i] == 9999) {
                // 如果从0点(起点)到i点最短路径是9999,即不可达
                // 则i节点的前驱节点不存在
                prev[i] = -1;
            } else {
                // 初始化i节点的前驱节点为起点,因为这个时候有最短路径的都是与起点直接相连的点
                prev[i] = v0;
            }
        }

        dist[v0] = 0;
        s[v0] = true;
    }

    /**
     * dijkstra核心算法
     */
    private void dijkstra() {
        for (int i = 1; i < PoiNum; ++i) { // 此时有PoiNum - 1个点在U集合中,需要循环PoiNum - 1次
            int minDist = 9999;
            int u = v0;

            for (int j = 1; j < PoiNum; ++j) { // 在U集合中,找到到起点最短距离的点
                if (!s[j] && dist[j] < minDist) { // 不在S集合,就是在U集合
                    u = j;
                    minDist = dist[j];
                }
            }
            s[u] = true; // 将这个点放入S集合

            for (int j = 1; j < PoiNum; ++j) { // 以当前刚从U集合放入S集合的点u为基础,循环其可以到达的点
                if (!s[j] && edges[u][j] < 9999) {
                    if (dist[u] + edges[u][j] < dist[j]) {
                        dist[j] = dist[u] + edges[u][j];
                        prev[j] = u;
                    }
                }
            }
        }
    }

    //    ArrayList<Integer> tep = new ArrayList<Integer>();
    int sum = 0;

    private int printDijkstra(int endPoiIndex, int[][] map) {

        if (endPoiIndex == v0) {
            System.out.println(indexPoiMap.get(v0) + ",");
//            return null;
        } else {
            printDijkstra(prev[endPoiIndex], map);
            System.out.println(indexPoiMap.get(endPoiIndex) + ","
                    + map[indexPoiMap.get(endPoiIndex).getX()][indexPoiMap.get(endPoiIndex).getY()]);
            sum += map[indexPoiMap.get(endPoiIndex).getX()][indexPoiMap.get(endPoiIndex).getY()];
//            tep.add(s);

        }
        return sum;
    }

    private List<Poi> getaroPois(Poi Poi) {
        List<Poi> aroPois = new ArrayList<>();
        int x = Poi.getX();
        int y = Poi.getY();
        aroPois.add(PoiPoiMap.get(new Poi(x - 1, y)));
        aroPois.add(PoiPoiMap.get(new Poi(x, y + 1)));
        aroPois.add(PoiPoiMap.get(new Poi(x + 1, y)));
        aroPois.add(PoiPoiMap.get(new Poi(x, y - 1)));
        aroPois.removeAll(Collections.singleton(null)); // 剔除不在地图范围内的null点
        return aroPois;
    }

    public static class Poi {
        private int x;
        private int y;
        private int value;

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

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

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

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return "{" +
                    "x=" + x +
                    ", y=" + y +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Poi Poi = (Poi) o;

            if (x != Poi.x) return false;
            return y == Poi.y;
        }

        @Override
        public int hashCode() {
            int result = x;
            result = 31 * result + y;
            return result;
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Python 中,有许多算法可以用来计算最短路径。其中包括 Dijkstra 算法、A* 算法、Bellman-Ford 算法和 Floyd-Warshall 算法。 Dijkstra 算法是一种贪心算法,用于计算单源最短路径。它适用于边权为非负的图。Dijkstra 算法的时间复杂度为 O(E log V),其中 E 和 V 分别表示边数和顶点数。 A* 算法是一种启发式搜索算法,用于计算单源最短路径。它的优势在于,它可以根据地图信息(例如路线长度、转弯次数等)估算剩余距离,并使用这些信息来更快地找到最短路径。 Bellman-Ford 算法是一种动态规划算法,用于计算单源最短路径。它可以处理边权可以为负的图,但是它的时间复杂度比 Dijkstra 算法差。 Floyd-Warshall 算法是一种动态规划算法,用于计算所有点对之间的最短路径。它的时间复杂度为 O(V^3),其中 V 表示顶点数。 你可以使用 Python 的第三方库,如 NetworkX、igraph 或 Boost.Graph,来轻松实现这些算法。 ### 回答2: Python中计算最短路径的算法有很多种,其中最常用的是Dijkstra算法和Floyd-Warshall算法。 Dijkstra算法是一种适用于有向图和带权边的最短路径算法。它通过不断选择当前最短路径长度的顶点来实现,直到找到终点或者所有顶点都被遍历完。算法的基本思想是,从起点开始,逐步确定所有顶点到起点的最短路径,并不断更新路径长度和路径距离。Dijkstra算法能够找到起点到终点的最短路径,并返回路径长度。 Floyd-Warshall算法是一种适用于有向图和带权边的所有最短路径算法。它通过动态规划的思想,逐步计算任意两个顶点之间的最短路径长度。算法的基本思想是,对于每一个顶点对(i,j),在考虑中间节点(1~n)的情况下,取其中路径长度最小的作为最终结果。Floyd-Warshall算法能够找到所有顶点之间的最短路径长度,以及路径信息。 在Python中,可以使用图论库networkx来实现最短路径算法。通过创建有向图,添加带权边,然后调用networkx库中的最短路径函数,即可计算最短路径。例如,可以使用networkx库中的dijkstra_path函数计算Dijkstra算法,或者使用networkx库中的floyd_warshall函数计算Floyd-Warshall算法。 总之,Python提供了丰富的图论库和算法函数,可以方便地计算最短路径。可以根据具体情况选择适合的算法,并结合相应的库函数进行实现。 ### 回答3: Python中有几种常见的计算最短路径的算法,如Dijkstra算法、Bellman-Ford算法和Floyd-Warshall算法。 Dijkstra算法是一种在加权图中计算单个源最短路径的贪心算法。其基本思想是根据起点到各个顶点的最短距离逐步扩展路径,直到达到目标顶点。在Python中,可以使用优先队列来实现Dijkstra算法。 Bellman-Ford算法是一种可以处理有向图和带有负权边的图的单源最短路径算法。该算法通过逐步迭代更新各个顶点的最短距离,直到没有更改为止。在Python中,可以使用邻接表或邻接矩阵来实现Bellman-Ford算法。 Floyd-Warshall算法用于计算所有顶点之间的最短路径。它通过逐步迭代来更新每对顶点之间的最短距离,直到得到所有顶点之间的最短路径。在Python中,可以使用二维数组或矩阵来实现Floyd-Warshall算法。 这些算法在Python中都有对应的实现,可以通过网络搜索相关的库或使用自己实现的代码来计算最短路径。例如,对于Dijkstra算法,可以使用heapq库中的heapq模块来实现优先队列,使用字典来存储顶点和距离的关系。对于Bellman-Ford算法和Floyd-Warshall算法,可以使用二维数组或矩阵来存储顶点之间的距离,并使用循环嵌套来进行更新和迭代。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值