2018 秋招 阿里巴巴 筆試測驗題 送快遞的最短路線

送快遞的最短路線

題目描述:

    某物流派送員p,須要給a、b、c、d4個快遞點派送包裹,請問派送員須要選擇什麼的路線,才能完成最短路程的派送。假設如圖派送員的起點座標(0,0),派送路線只能沿着圖中的方格邊行駛,每一個小格都是正方形,且邊長爲1,如p到d的距離就是4。隨機輸入n個派送點座標,求輸出最短派送路線值(從起點開始完成n個點派送並回到起始點的距離)。測試

思路:

    老實說,筆者剛開始拿到這個圖有些大意,想用DP試着解下,可是發現有些困難,隨後就換了種想法,將全部可能的路線都計算一遍,比較大小,求出最小的那個(全排列的思想)。因而,使用了以下的第一種解法:this

public class Main {
    private static int min = Integer.MAX_VALUE;// 預設的保存最後結果的變量
    private static Point pStart = new Point(0,0);// 用做測試的起點
    public static void main(String[] args) {
        Point[] points = new Point[4];
        points[0] = new Point(3,1);
        points[1] = new Point(2,2);
        points[2] = new Point(5,3);
        points[3] = new Point(1,4);
        DFSSolver(points,pStart,0,0);
        System.out.println(min);
    }

    /**
     * 全排列的方式將全部路徑都嘗試了一編
     * 循環遍歷每一個起點,而後從選擇的起點開始進行深度優先遍歷,遍歷完記錄sum值若是比min小就替換了
     * 採用形參的方式 維護了咱們邏輯棧的變量:start、sum、count
     * @param points 全部可選起點集
     * @param start 這次選擇的起點
     * @param sum 到此時,走過的路長
     * @param count 用來記錄這次深度遍歷是否結束
     * @return
     */
    public static void DFSSolver(Point[] points, Point start, int sum, int count) {
        for (int i = 0; i < points.length; i++) {// 決定以哪一個爲起點
            if(! points[i].passed){ // 若是此點訪問過則繼續
                points[i].passed = true; // 沒有則修改成訪問過
                count++;// 記錄在這次選擇了起點的後,已經遍歷到哪一個點了
                sum+=start.showDistance(points[i]);// 將這次起點到這個點的距離算上
                if(count==points.length){// 這個if纔是決定最短的那條路線的長度
                    sum+=points[i].showDistance(pStart);// 將這個點到最初的起點的距離算上
                    if(sum<min){
                        min = sum;
                    }
                    System.out.println("i="+i+"; sum="+sum+"; min="+min);
                }
                DFSSolver(points, points[i],sum,count);// 遞歸調用,繼續尋找下一個未訪問過的點,若是都訪問過了,那麼就執行回退,回退到上一個點尋找未訪問過的點
                points[i].passed = false;// 回退一格
                sum-=start.showDistance(points[i]);// 回退計算路徑長度
                count --;// 回退計算訪問過的點數
            }
        }
    }

	/**
     * 表示圖中的點集
     */
    static class Point {
        int x;// 表示點的X軸的值
        int y;// 表示點的Y軸的值
        boolean passed = false;

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

		/**
         * 顯示此點與指定點的距離
         * @param anotherPoint
         * @return
         */
        public int showDistance(Point anotherPoint) {
            return Math.abs(x - anotherPoint.x) + Math.abs(y - anotherPoint.y);
        }
    }
}

結果如圖:code

全排列結果

    交完卷後,粗略地瀏覽了下各路大神的解題思路,發現了一個哥們的想法頗有意思,可是略微有些不明白的地方blog

    解題思路轉自:傳送門遞歸

    簡單歸納下:求出包括全部點的最小正方型。get

    可是這樣的話,若是內部點有出現重複路徑的,就沒辦法判斷出來了好像...,筆者按照這樣的思路試了下發現答案好像不太對:it

Code:class

/**
     * 表示圖中的點集
     */
    static class Point{
        int px;
        int py;
        boolean isVisited = false;
        public Point(int xValue,int yValue){
            px = xValue;
            py = yValue;
        }
    }

    public static void main(String[] args){
        int x = Integer.MIN_VALUE;
        int y = Integer.MIN_VALUE;
        int xStart = 0;
        int yStart = 0;
        Point[] points = new Point[]{new Point(3,1),new Point(2,2),new Point(5,3),new Point(1,4)};
        for(Point p : points){
            x = p.px>x?p.px:x;
            y = p.py>y?p.py:y;
        }
        System.out.println((x-xStart+y-yStart)<<1);
    }

結果好像不太對

嗯,就先記錄到這吧!但願能有dalao指教下小弟,若是有更好的辦法!畢竟全排列的解法屬於挺暴力的解法的!(逃..變量

相關文章
相關標籤/搜索