首页 > 试题广场 >

邮局选址问题

[编程题]邮局选址问题
  • 热度指数:997 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
一条直线上有居民点,邮局只能建在居民点上。给定一个有序整形数组arr,每个值表示居民点的一维坐标,再给定一个正数num,表示邮局数量。
选择num个居民点建立num个邮局,使所有的居民点到邮局的总距离最短,返回最短的总距离。

输入描述:
第一行有两个整数N,num。分别表示居民点的数量,要建的邮局数量。
接下来一行N个整数表示邮局的坐标。保证坐标递增


输出描述:
输出一个整数表示答案
示例1

输入

6 2
1 2 3 4 5 1000

输出

6

说明

第一个邮局建立在3位置,第二个邮局建立在1000位置。那么1位置到邮局的距离为2,2位置到邮局距离为1,3位置到邮局的距离为0,4位置到邮局的距离为1,5位置到邮局的距离为2,1000位置到邮局的距离为0.
这种方案下的总距离为6。

备注:


import java.util.Map;
import java.util.Scanner;

public class Main {

    private static int[][] getRecord(int[] arr) {
        int[][] record = new int[arr.length][arr.length];
        for (int i = 0; i < arr.length; ++i) {
            for (int j = i + 1; j < arr.length; ++j) {
                record[i][j] = record[i][j - 1] + arr[j] - arr[(i + j) >> 1];
            }
        }
        return record;
    }

    /**
     * 四边形不等式优化
     *
     * @param arr
     * @param m
     * @return
     */
    private static int solvePlus(int[] arr, int m) {
        if (arr == null || arr.length == 0) {
            return 0;
        }

        int n = arr.length;
        int[][] record = getRecord(arr);
        m = Math.min(n, m);
        int[][] dp = new int[n][m];
        int[][] choose = new int[n][m];

        for (int i = 0; i < n; ++i) {
            dp[i][0] = record[0][i];
            choose[i][0] = (i + 1)/ 2;
        }

        for (int i = 1; i < n; ++i) {
            for (int j = Math.min(m - 1, i); j >= 1; --j) {
                dp[i][j] = record[0][i];
                int up = j == Math.min(m - 1, i) ? i : Math.min(i, choose[i][j + 1]);
                int down = Math.max(1, choose[i - 1][j]);

                for (int s = up; s >= down; --s) {
                    if (dp[i][j] > dp[s - 1][j - 1] + record[s][i]) {
                        dp[i][j] = dp[s - 1][j - 1] + record[s][i];
                        choose[i][j] = s;
                    }
                }
            }
        }

        return dp[n - 1][m - 1];
    }

    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int n = in.nextInt();
            int m = in.nextInt();
            int[] arr = new int[n];
            for (int i = 0; i < n; ++i) {
                arr[i] = in.nextInt();
            }
            System.out.println(solvePlus(arr, m));
        }
    }
}

发表于 2022-07-30 14:43:29 回复(0)

问题信息

上传者:小小
难度:
2条回答 7087浏览

热门推荐

通过挑战的用户

查看代码