最短路径算法(递归)


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Kevin
 * @data 4/24/2022 8:48 PM
 * @description Agv小车最短路径计算
 **/
public class AgvLoader {

  public static void main(String[] args) {

    calculate(allNode.get(2),allNode.get(12),new ArrayList<Integer>(),0);
    System.out.println("最佳路径是");
    System.out.println(bestLoad);
    System.out.println("最佳路径长度是");
    System.out.println(bestLen);

  }


  /**
   * 地图上的点实体类,有向图实现
   */
  public static class Node{

    // 节点标识
    public Integer id;

    // 可以到达的节点标识集合
    public List<Integer> next;

    public Node(Integer id, List<Integer> next) {
      this.id = id;
      this.next = next;
    }

    public Integer getId() {
      return id;
    }

    public void setId(Integer id) {
      this.id = id;
    }

    public List<Integer> getNext() {
      return next;
    }

    public void setNext(List<Integer> next) {
      this.next = next;
    }
  }

  // 全局点位Map
  private static Map<Integer,Node> allNode = new HashMap<>();

  // 全局相邻点位的路径和 key是两相邻点位map
  private static Map<HashMap<Integer,Integer>,Integer> allLen = new HashMap<>();

  // 记录最佳路径集合
  private static List<Integer> bestLoad = new ArrayList<>();

  // 记录最佳路径的路径和
  private static Integer bestLen = Integer.MAX_VALUE;

  static {
    // 初始化路径map
    ArrayList<Integer> integers1 = new ArrayList<>();
    integers1.add(2);
    integers1.add(5);
    allNode.put(1,new Node(1,integers1));

    ArrayList<Integer> integers2 = new ArrayList<>();
    integers2.add(1);
    integers2.add(3);
    allNode.put(2,new Node(2,integers2));

    ArrayList<Integer> integers3 = new ArrayList<>();
    integers3.add(2);
    integers3.add(6);
    integers3.add(4);
    allNode.put(3,new Node(3,integers3));

    ArrayList<Integer> integers4 = new ArrayList<>();
    integers4.add(3);
    integers4.add(8);
    allNode.put(4,new Node(4,integers4));

    ArrayList<Integer> integers5 = new ArrayList<>();
    integers5.add(1);
    integers5.add(6);
    integers5.add(9);
    allNode.put(5,new Node(5,integers5));

    ArrayList<Integer> integers6 = new ArrayList<>();
    integers6.add(5);
    integers6.add(7);
    integers6.add(9);
    integers6.add(11);
    allNode.put(6,new Node(6,integers6));

    ArrayList<Integer> integers7 = new ArrayList<>();
    integers7.add(6);
    integers7.add(8);
    allNode.put(7,new Node(7,integers7));

    ArrayList<Integer> integers8 = new ArrayList<>();
    integers8.add(4);
    integers8.add(7);
    integers8.add(12);
    allNode.put(8,new Node(8,integers8));

    ArrayList<Integer> integers9 = new ArrayList<>();
    integers9.add(5);
    integers9.add(10);
    allNode.put(9,new Node(9,integers9));

    ArrayList<Integer> integers10 = new ArrayList<>();
    integers10.add(9);
    integers10.add(11);
    allNode.put(10,new Node(10,integers10));

    ArrayList<Integer> integers11 = new ArrayList<>();
    integers11.add(10);
    integers11.add(12);
    allNode.put(11,new Node(11,integers11));

    ArrayList<Integer> integers12 = new ArrayList<>();
    integers12.add(8);
    integers12.add(11);
    allNode.put(12,new Node(12,integers12));

    // 初始化点位距离map
    allLen.put(creatAllLenKey(1,2),50);
    allLen.put(creatAllLenKey(2,3),5);
    allLen.put(creatAllLenKey(6,3),5);
    allLen.put(creatAllLenKey(6,11),5);
    allLen.put(creatAllLenKey(3,4),5);
    allLen.put(creatAllLenKey(4,8),5);
    allLen.put(creatAllLenKey(8,7),5);
    allLen.put(creatAllLenKey(7,6),5);
    allLen.put(creatAllLenKey(6,5),5);
    allLen.put(creatAllLenKey(6,9),5);
    allLen.put(creatAllLenKey(5,1),5);
    allLen.put(creatAllLenKey(5,9),5);
    allLen.put(creatAllLenKey(9,10),5);
    allLen.put(creatAllLenKey(10,11),5);
    allLen.put(creatAllLenKey(11,12),5);
    allLen.put(creatAllLenKey(12,8),5);


  }



  /**
   * 计算最短路径
   * @param start 起点
   * @param end 终点
   * @param currentThrough 当前经过的点位集合
   * @param currentLength 当前经过的点位路径长度
   */
  public static void calculate(Node start, Node end, List<Integer> currentThrough, Integer currentLength){

    // 边界判断
    if (start == null || end == null){
      return;
    }

    // 如果当前路径和大于已经找到的最小路径和 那就可以直接返回了
    if (currentLength >= bestLen){
      return;
    }

    // 找到了
    if (start == end){

      currentThrough.add(end.getId());
      System.out.print("找到了-->");
      System.out.print(currentThrough);
      System.out.print("路径和是--->");
      System.out.println(currentLength);

      // 保存最佳路径 前面已经判断,这里无需判断
      bestLoad = currentThrough;
      bestLen = currentLength;

      return;
    }

    // 这个判断要放到最下面
    if (start.next == null || start.next.size() == 0){
      return;
    }

    // 又回到经过的点了,直接返回
    if (currentThrough.contains(start.getId())){
      return;
    }


    // 将start存入当前经过的点位集合
    currentThrough.add(start.getId());


    // 递归寻找下面在全局经过点位里不存在的点
    List<Integer> noThrough = new ArrayList<>();

    for (Integer integer : start.next) {
      if (!currentThrough.contains(integer)){
        noThrough.add(integer);
      }
    }

    // 如果所有点都已经经过了,那就直接返回
    if (noThrough.size() == 0){
      return;
    }else {
      for (Integer integer : noThrough) {
        // 这里需要拷贝一份进行传递,不能传入引用地址
        calculate(allNode.get(integer),end,copyList(currentThrough),currentLength + getLen(start.getId(),integer));
      }
    }

  }


  /**
   * 创建allLen的key
   * @param n1
   * @param n2
   * @return
   */
  public static HashMap<Integer,Integer> creatAllLenKey(int n1, int n2){
    HashMap<Integer, Integer> map = new HashMap<>();
    map.put(n1,n2);
    return map;
  }

  /**
   * 获取两点间的距离
   * @param n1
   * @param n2
   * @return
   */
  public static Integer getLen(int n1, int n2){
    HashMap<Integer, Integer> key1 = creatAllLenKey(n1, n2);
    Integer value1 = allLen.get(key1);
    if (value1 != null){
      return value1;
    }else {
      return allLen.get(creatAllLenKey(n2, n1)) ;
    }
  }

  /**
   * List拷贝
   * @param list
   * @return
   */
  public static List<Integer> copyList(List<Integer> list){
    ArrayList<Integer> copy = new ArrayList<>();
    copy.addAll(list);
    return copy;
  }



}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值