1. 程式人生 > >阿里線上程式設計測試題--派送貨物,求最短路徑

阿里線上程式設計測試題--派送貨物,求最短路徑

阿里線上程式設計測試題–派送貨物,求最短路徑

題目

如下圖,某物流派送員p,需要給 a、b、c、d. 4個快遞點派送包裹,請問派送員需要選擇什麼樣的路線,才能完成最短路程的派送。假設如圖派送員的起點座標(0,0),派送路線只能沿著圖中的方格邊行駛,每個小格都是正方形,且邊長為1,如p到d的距離就是4。隨機輸入n個派送點座標,求輸出最短派送路線值(從起點開始完成n個點派送並回到起始點的距離)。
這裡寫圖片描述
輸入示例:
4
2,2
2,8
4,4
7,2
輸出:
30

思考過程

我首先想到的是把所有的路徑都嘗試一次,並求出每條路徑的總路程,從中選取最短的一條。核心思想就是全排列。後來想到了用回溯法解決:選擇所有送貨點中的任意一點作為第一個送貨點,然後繼續往下搜尋下一個點,直到將所有點都走過一遍,到達最後一個點時求出總路程並返回。這裡使用了遞迴,最難的地方在於回溯時要回到什麼地方,為了解決這個問題,需要引入一個表示送貨點狀態的boolean陣列,回溯之後靠這個陣列進入別的未嘗試過的路徑。

程式碼如下

//路徑中的點
    static class Point{
        private int x;
        private int y;
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getDistance(Point point) {
            return Math.abs(this.x - point.x) + Math.abs(this.y - point.y);
        }
    }

    public
static void main(String[] args) { int pointNum = 0; Scanner sc = new Scanner(System.in); pointNum = Integer.parseInt(sc.nextLine().trim()); Point[] points = new Point[pointNum]; //設(0,0)點為起點 start = new Point(0, 0); //輸入送貨點座標x,y for(int i = 0; i < pointNum; i++) { String[] locations = sc.nextLine().trim().split(","
); points[i] = new Point(Integer.parseInt(locations[0]), Integer.parseInt(locations[1])); } sc.close(); System.out.println(getMinDistance(pointNum, points)); } private static Point start; //將minDistance的初始值設為無窮大,即沒找到最短路徑 private static int minDistance = Integer.MAX_VALUE; /** * @param pointNum:送貨點數量 * @param points:送貨點陣列 */ public static int getMinDistance(int pointNum, Point[] points) { int distance = 0; //flag陣列用於標記該點是否已搜尋 boolean[] flag = new boolean[pointNum]; //分別將各個點作為第一個送貨點進行搜尋 for(int i = 0; i < pointNum; i++) { distance += start.getDistance(points[i]); DFSSearch(i, distance, flag, points, 1, pointNum); } return minDistance; } /** * * @param index:當前點 * @param distance:當前路徑長度 * @param flag:是否在該路徑的標誌,true為在,false為不在 * @param points:送貨點陣列 * @param level:搜尋深度,即搜尋到第幾個點 * @param allLevel:搜尋總深度,一共要搜尋幾個點 */ private static void DFSSearch(int index, int distance, boolean[] flag, Point[] points, int level, int allLevel) { if(level == allLevel) { //搜尋到最後一個點時計算其與起點的距離,求得整個送貨過程的總路程 distance += start.getDistance(points[index]); if(distance < minDistance) { minDistance = distance; } return; } //將當前路徑標記為true,表示在當前路徑上 flag[index] = true; for(int i = 0; i < points.length; i++) { //前往下一條沒有被搜尋過得路徑 //條件為該路徑的flag為false if(!flag[i]) { //先計算當前這個點與即將前往的下一個點之間的距離 distance += points[index].getDistance(points[i]); //繼續往下搜尋 //此時搜尋深度+1 DFSSearch(i, distance, flag, points, level+1, allLevel); } } //當前點已搜尋完,退出當前路徑,返回上一個點 //將當前路徑的flag設為false flag[index] = false; }