某物流派送員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指教下小弟,若是有更好的辦法!畢竟全排列的解法屬於挺暴力的解法的!(逃..變量