1478. 安排邮筒 Krains 2020-07-30 14:51:32 动态规划DFS数学
时间:2022-07-22
本文章向大家介绍1478. 安排邮筒 Krains 2020-07-30 14:51:32 动态规划DFS数学,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
# 题目链接
本题跟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]kin[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
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 慎用JSON.stringify
- 【Java8新特性】04 详解Lambda表达式中Predicate Function Consumer Supplier函数式接口
- ubuntu下的进程控制系统————Supervisor
- 如何高效、快速、准确地完成ML任务,这4个AutoML库了解一下
- [译]如何用 Typescript 写一个完整的 Vue 应用程序
- Docker上手系列:Docker入门hello world
- 前端应该知道的 HTTP 知识
- React 学习笔记(基础篇)
- 前端性能优化《一》——Chrome Performance 页面性能调试
- 【Vue 进阶】从 slot 到无渲染组件
- 一个合格的中级前端工程师应该掌握的 20 个 Vue 技巧
- Vue 3 任意传送门——Teleport
- @JsonCreator自定义反序列化函数-JSON框架Jackson精解第5篇
- 不靠谱的 console
- 使用ThreadLocal和ArgumentResolver方便开发