(java实现)
题目描述:
一个数轴上共有N个点,第一个点的坐标是度度熊现在位置,第N-1个点是度度熊的家。现在他需要依次的从0号坐标走到N-1号坐标。
但是除了0号坐标和N-1号坐标,他可以在其余的N-2个坐标中选出一个点,并直接将这个点忽略掉,问度度熊回家至少走多少距离?
输入描述:
输入一个正整数N, N <= 50。
接下来N个整数表示坐标,正数表示X轴的正方向,负数表示X轴的负方向。绝对值小于等于100
输出描述:
输出一个整数表示度度熊最少需要走的距离。
示例1:
输入
4
1 4 -1 3
输出
4
问题分析:
由于走的坐标点是按照输入顺序“依次”走的,不能打乱顺序,因此不能通过简单排序来实现。故:本题考虑动态规划的思想,寻找最短路径。
若从N-2个坐标中选出一个点,并直接将这个点忽略掉。直接忽略一个点只会直接影响到,这个节点前后节点的距离。这个影响的距离我们暂且命名为优化距离,将所有节点按顺序组成三个节点的集合,通过这种方式只需要通过一次循环便能得到结果。
题目的关键问题其实就是如何可以去掉走的路最多的那个点。一个点走的路与前后两个点都有关,所以探讨一个点走的路,需要三个点一起看。
假设中间点的位置是i,如果不删除它,走的路程如下:
Math.abs(p[i]-p[i-1])+Math.abs(p[i]-p[i+1]);
若删除掉它之后所走的路程如下:
Math.abs(p[i-1]-p[i+1]);
接下来两者做差,算出来的就是去掉之后可以节省的路程。
然后找出能节省的路程最多的那个点。
最终的结果就是减去能节省的最多的路程。
思路一:暴力法。依次去掉每个点,然后计算获取最小值。
思路二:使用动态规划的思想,寻找差值最大的点(分析如上),然后将其删除。
相关知识:
绝对值函数:Math.abs(number);
参考代码:
思路一实现:
import java.util.*; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); while (input.hasNext()) { int n = input.nextInt(); int[] arr = new int[n]; for (int i=0; i<n; i++) { arr[i] = input.nextInt(); } int min = Integer.MAX_VALUE; //max int tmp = 0; int sum = 0; for (int i=1; i<n-1; i++) { tmp = arr[i]; //通过原地打转来实现删除点 arr[i] = arr[i-1]; min = getLen(arr,min,n); arr[i] = tmp; } System.out.println(min); } } //在删除某个点后,计算其路程 public static int getLen(int[] arr, int min, int n) { int sum = 0; for (int i=1; i<n; i++) { sum += Math.abs(arr[i]-arr[i-1]); } if (sum < min) return sum; return min; } }
思路二实现:
import java.util.*; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); while (input.hasNext()) { int n = input.nextInt(); int[] arr = new int[n]; int sum = 0; arr[0] = input.nextInt(); for (int i=1; i<n; i++) { arr[i] = input.nextInt(); sum += Math.abs(arr[i]-arr[i-1]); } int max = Integer.MIN_VALUE; //max for (int i=1; i<n-1; i++) { int len1 = Math.abs(arr[i]-arr[i-1])+Math.abs(arr[i]-arr[i+1]); int len2 = Math.abs(arr[i+1]-arr[i-1]); if (max < (Math.abs(len1-len2))) max = Math.abs(len1-len2); } System.out.println(sum-max); } } }