ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

邮局选址问题

2021-10-20 15:03:38  阅读:398  来源: 互联网

标签:arr record 邮局 ++ 问题 int length 选址 dp


链接:https://www.nowcoder.com/questionTerminal/8b0152848ffd475eaa950278606fe70b
来源:牛客网
一条直线上有居民点,邮局只能建在居民点上。给定一个有序整形数组arr,每个值表示居民点的一维坐标,再给定一个正数num,表示邮局数量。 选择num个居民点建立num个邮局,使所有的居民点到邮局的总距离最短,返回最短的总距离。

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 solve(int[] arr, int m) {
        if (arr == null || arr.length == 0) {
            return 0;
        }

        int n = arr.length;
        int[][] record = getRecord(arr);
        int[][] dp = new int[n][n];

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

        for (int i = 1; i < n; ++i) {
            for (int j = 1; j < Math.min(m, i + 1); ++j) {
                dp[i][j] = record[0][i];
                for (int s = i; s > 0; --s) {
                    dp[i][j] = Math.min(dp[i][j], dp[s - 1][j - 1] + record[s][i]);
                }
            }
        }

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

    /**
     * 四边形不等式优化
     *
     * @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);
        int[][] dp = new int[n][n];
        int[][] choose = new int[n][n];

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

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

标签:arr,record,邮局,++,问题,int,length,选址,dp
来源: https://www.cnblogs.com/tianyiya/p/15428826.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有