前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >1478. 安排邮筒 Krains 2020-07-30 14:51:32 动态规划DFS数学

1478. 安排邮筒 Krains 2020-07-30 14:51:32 动态规划DFS数学

作者头像
Krains
发布2020-08-05 11:36:09
3720
发布2020-08-05 11:36:09
举报
文章被收录于专栏:KrainsKrainsKrains

# 题目链接

本题跟410. 分割数组的最大值 差不多,该题的题解

思路:将这条街分为几块区域,每个区域安排一个邮筒。在一个区域中,要想邮筒到该区域所有房子的距离之和最小,邮筒应该安排在这些房子位置的中位数上,这时邮筒到它们的距离总和最小(可由绝对值不等式证明)。

# DFS记忆化

首先先求出区域[i, j]安排一个邮筒的到区域内各个房子距离之和最小值,然后dfs搜索所有划分点,求出所有划分中各区域到邮筒距离之和的最小值。

class Solution {
    // cost[i][j]表示在区域[i, j]中安排一个邮筒到该区域其他房子的距离之和的最小值
    int[][] cost;
    int n;

    public int minDistance(int[] houses, int m) {
        Arrays.sort(houses);
        n = houses.length;
        cost = new int[n][n];
        for(int i = 0; i < n; i++){
            for(int j = i; j < n; j++){
                for(int k = i; k <= j; k++){
                    cost[i][j] += Math.abs(houses[k] - houses[i+(j-i+1)/2]);
                }
            }
        }

        return helper(0, 0, m, new Integer[n+1][m+1]);
    }

    // [i, n)是待划分的区域,j表示当前第几个划分
    public int helper(int i, int j, int m, Integer[][] memo){
        if(memo[i][j] != null)
            return memo[i][j];

        // 划分结束且最后一组不为空,直接返回最后一组区域[i, n)要花费的代价
        if(j + 1 == m && i < n)
            return cost[i][n-1];

        int min = Integer.MAX_VALUE / 2;
        // 穷尽所有的划分点
        for(int k = i; k < n; k++){
            // [i, k]是当前划分,[k+1, n)是后面的划分
            min = Math.min(min, cost[i][k] + helper(k+1, j+1, m, memo));
        }

        // 记忆
        return memo[i][j] = min;
    }
}

# 动态规划

状态表示

  • 集合:(i,j)(i, j)(i,j)表示前i所房子分配j个邮筒的所有分法。
  • 属性:f(i,j)f(i, j)f(i,j)表示所有分法中各个房子到其最近邮筒的距离最小和。

状态计算/集合划分

假设最后一个划分位置在k,k∈[0,i]k\in[0, i]k∈[0,i],那么

f(i,j)=f(k−1,j−1)+cost[k][i]f(i,j)=f(k-1,j-1)+cost[k][i] f(i,j)=f(k−1,j−1)+cost[k][i]

表示将前k-1所房子分配j-1个邮筒的距离最小和加上本次分配的邮筒所产生的距离和。

class Solution {
    int[][] cost;
    int n;

    public int minDistance(int[] houses, int m) {
        Arrays.sort(houses);
        n = houses.length;
        cost = new int[n][n];
        for(int i = 0; i < n; i++){
            for(int j = i; j < n; j++){
                for(int k = i; k <= j; k++){
                    cost[i][j] += Math.abs(houses[k] - houses[i+(j-i+1)/2]);
                }
            }
        }

        int[][] dp = new int[n][m+1];

        for(int i = 0; i < n; i++) 
            dp[i][0] = Integer.MAX_VALUE / 2;
        
        for(int i = 1; i < n; i++){
            for(int j = 1; j <= m; j++){
                dp[i][j] = Integer.MAX_VALUE / 2;
                for(int k = 0; k <= i; k++){
                    int t = 0;
                    if(k != 0) t = dp[k-1][j-1];
                    dp[i][j] = Math.min(dp[i][j], t + cost[k][i]);
                }
            }
        }

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

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=h9nz2zbl70v8

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • # 题目链接
  • # DFS记忆化
  • # 动态规划
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档