(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);
}
}
}