Java USACO如何解决/理解Marathon的解决方案(青铜2014年12月)?

时间:2014-12-23 04:03:43

标签: java algorithm math

这是问题所在。

这是解决方案。

我已经解决了这个问题但是我的代码太慢而无法通过所有测试用例直到100,000点,所以我读了官方解决方案,但我无法理解解决方案,数学部分说:

int largestSkip = 0;
    for(int i = 1; i < n-1; i++) {
      int noSkipDistance = Math.abs(x[i+1] - x[i]) + Math.abs(x[i] - x[i-1]) + Math.abs(y[i+1] - y[i]) + Math.abs(y[i] - y[i-1]);
      int skipDistance = Math.abs(x[i+1] - x[i-1]) + Math.abs(y[i+1] - y[i-1]);
      largestSkip = Math.max(largestSkip, noSkipDistance - skipDistance);
    }

他们如何获得这些公式?如果我理解变量skipDistance从0开始 - 跳过1-2,1-跳过2 -3,依此类推,其他变量noskipDistance从0 -2开始,1 - 3(没有跳过)等等,还有其他类似的问题吗?或者如果有人能帮助我理解我会非常感激

我想到的最佳解决方案是,但它太慢了

import java.io.*;
import java.util.*;
public class marathon {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("marathon.in"));
        PrintWriter pw = new PrintWriter(new File("marathon.out"));
        int n = Integer.parseInt(br.readLine());
        int[][] arr = new int[n][2];
        boolean[] flag = new boolean[n];

        for(int i = 0; i < n; i++){
            String s = br.readLine();
            int n1 = Integer.parseInt(s.substring(0 , s.indexOf(" ")));
            int n2 = Integer.parseInt(s.substring(s.indexOf(" ") +1, s.length()));
            arr[i][0] = n1;
            arr[i][1] = n2;
        }
        Arrays.fill(flag, true);
        long min = Long.MAX_VALUE;

        for(int i = 1; i < (n -1); i++){
            flag[i] = false;
            min = Math.min(min, solve(arr, flag, n));
            flag[i] = true;
        }
        pw.println(min);
        pw.close();
    }

    public static long solve(int[][]arr, boolean[] flag, int n){
        long min = Long.MAX_VALUE;
        long sum = 0;
        List<Integer> listX = new ArrayList<>();
        List<Integer> listY = new ArrayList<>();
        listX.add(arr[0][0]);
        listY.add(arr[0][1]);
        for(int i = 1; i < n -1; i++){
            if(flag[i]){
                listX.add(arr[i][0]);   
                listY.add(arr[i][1]);
            }
        }
        listX.add(arr[n-1][0]); 
        listY.add(arr[n-1][1]);

        for(int i = 1; i < listX.size(); i++){
            sum = Math.abs(listX.get(i -1) - listX.get(i)) +   Math.abs(listY.get(i -1) - listY.get(i)) + sum;
        }
        return sum;
    }
}

1 个答案:

答案 0 :(得分:3)

此解决方案中发生的事情是他们的社论中所写的内容。在每个点上,它计算如果选择该点作为跳跃点将会有效的长度 对于eq:
如果有四个点(a,b,c,d)并且你处于'a'点。您可以转到'b'或跳过'b'。

  • 如果你去'b',行进的距离是:曼哈顿距离a - &gt; b + b - &gt; C; (让我们称之为X)

  • 如果你跳过'b',行进的距离是:曼哈顿距离a - > c; (称之为Y)

通过选择此选项获得距离= X - Y.

您的目标是找到最大增益并选择给出它的点。
最后,ans是:所有曼哈顿距离的总和 - 最大增益。