路径规划的优化

因为这个求N个点的最短路径是将把所有可能的走法都可能尝试一遍,这样的话,如果计算十几个点之间的最短路径是没有问题的,但是问题就在如果超过二十个点位,那么最坏的情况就是需要计算20的阶乘个,这个计算是相当高的,可能会把线上的服务器打爆,或者计算几分钟,这都是不能忍受的,下面是我对这个算法的一些优化

/*
求出最短路径
 */
public class MinDis {

    static  double INF = 1e7;
    static  int N = 100;
    static  double[][] matrix ;  //地图矩阵
    static  Node min;
    static  double bestl = INF;// 记录当前最短的路径长度
    static  List<Integer> nodes = new ArrayList<Integer>();
    static  PriorityQueue<Node> priorityQueue = new PriorityQueue<>(N);


    // 优先队列的分支界限法搜索
    public LinkedHashSet<Integer> Traveling(double[][] matrix){
        for (int i = 2; i < matrix.length; i++) {
            nodes.add(i);
        }
        //生成根节点
        Node root = new Node(0, 1);
        root.notThrough.addAll(nodes);
        root.throughed.add(1);
        // 生成所有要走的点节点
        priorityQueue.add(root);
        while (!priorityQueue.isEmpty()){
            // 取出头部元素作为扩展节点
            Node poll = priorityQueue.poll();
            // 如果当前的未到达路径只有一个  不需要往下搜索
            if (poll.notThrough.size()==1){
                for (Integer not: poll.notThrough) {
                    // 如果当前节点和未达节点可联通
                    if (matrix[poll.id][not]!=INF && matrix[poll.id][not]+poll.c1 < bestl ){
                        bestl = matrix[poll.id][not]+poll.c1;
                        poll.throughed.add(not);
                        min=poll;
                    }
                }
            }

            // 如果没有到达子节点 遍历该节点没有经过的节点
            for (Integer noThrough : poll.notThrough){
                // 如果当前节点和未达节点不可联通
                if (matrix[poll.id][noThrough]==INF){
                    continue;
                }
                //并且 到达的路径小于当前最优解
                if (matrix[poll.id][noThrough]+poll.c1  <  bestl){
                    // 生成一个新结点
                    Node newNode = new Node(matrix[poll.id][noThrough] + poll.c1, noThrough);
                    HashSet<Integer> noth = new HashSet<>(poll.notThrough);
                    noth.remove(noThrough);
                    // 新结点去除上一个节点没通过的自己的Id
                    newNode.notThrough.addAll(noth);
                    // 新结点保存之前node经过的点
                    newNode.throughed.addAll(poll.throughed);
                    // 新结点记录经过的点
                    newNode.throughed.add(noThrough);
                    priorityQueue.add(newNode);
                }
            }
        }
//        System.out.println(bestl);
//        System.out.println(min.throughed);
        return min.throughed;
    }

    //内部类 node  //根据c1大小实现优先级
     class Node implements Comparable<Node> {
        public double c1; // 当前已走过的路径长度
        public int id; //点序号
        public LinkedHashSet<Integer> throughed; // 当前已走过的点序号
        public HashSet<Integer> notThrough; //当前未走过的点序号

        public Node(double c1, int id) {
            this.c1 = c1;
            this.id = id;
            this.notThrough= new HashSet<>();
            this.throughed=new LinkedHashSet<>();
        }
        @Override
        public int compareTo(Node o) {
            return (int) (this.c1-o.c1);
        }
    }



    // 传入N个位置点 生成每个点之间距离的矩阵
    public  double[][] createMatrix(List<double[]> locations){
        int row = locations.size()+1;
        double[][] matrix = new double[row][row];
        // 遍历点位
        for (int i = 0; i < locations.size(); i++) {
            double[] A = locations.get(i);
            // 遍历每一个点到其他点的距离
            for (int j = i; j < locations.size() ; j++) {
                if(i==j){
                    matrix[i+1][i+1]=INF;
                    continue;
                }
                double[] B = locations.get(j);
                double distance = GPSUtil.Distance(A[1], A[0], B[1], B[0]);
                // 矩阵填充
                matrix[i+1][j+1] = distance;
                matrix[j+1][i+1] = distance;
            }
        }
        return matrix;
    }

这个算法的缺点在于 这个优先队列 是根据当前的路径长度来判断计算的优先级的 当前走过的路径越短 优先级就越高 但是这个本身就是有问题的,如果根据这个来判断那么就会遍历的点位可能特别多
我在网上搜了好久 也没发现太好的算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值