某物流派送员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指教下小弟,若是有更好的办法!毕竟全排列的解法属于挺暴力的解法的!(逃..变量