2023-05-06:X轴上有一些机器人和工厂。给你一个整数数组robot,其中robot[i]是第i个机器人的位置 再给你一个二维整数数组factory,其中 factory[j] = [posit
2023-05-06:X轴上有一些机器人和工厂。给你一个整数数组robot,其中robot[i]是第i个机器人的位置
再给你一个二维整数数组factory,其中 factory[j] = [positionj, limitj]
表示第 j 个工厂的位置在 positionj ,且第 j 个工厂最多可以修理 limitj 个机器人
每个机器人所在的位置 互不相同。每个工厂所在的位置也互不相同
注意一个机器人可能一开始跟一个工厂在相同的位置
所有机器人一开始都是坏的,他们会沿着设定的方向一直移动
设定的方向要么是 X 轴的正方向,要么是 X 轴的负方向
当一个机器人经过一个没达到上限的工厂时,这个工厂会维修这个机器人,且机器人停止移动
任何时刻,你都可以设置 部分 机器人的移动方向
你的目标是最小化所有机器人总的移动距离
请你返回所有机器人移动的最小总距离
注意:
所有机器人移动速度相同
如果两个机器人移动方向相同,它们永远不会碰撞
如果两个机器人迎面相遇,它们也不会碰撞,它们彼此之间会擦肩而过
如果一个机器人经过了一个已经达到上限的工厂,机器人会当作工厂不存在,继续移动
机器人从位置 x 到位置 y 的移动距离为 |y - x|
1 <= robot.length, factory.length <= 100
factory[j].length == 2
-10 ^ 9 <= robot[i], positionj <= 10 ^ 9
0 <= limitj <= robot.length
测试数据保证所有机器人都可以被维修。
输入:robot = [0,4,6], factory = [[2,2],[6,2]]。
输出:4。
答案2023-05-06:
算法1:
1.首先对机器人位置数组 robot
进行排序,按照从小到大的顺序排列。
2.对工厂位置数组 factory
按照第一个元素排序,也就是按照工厂所在的位置从小到大排列。
3.创建一个二维数组 dp
,大小为 (n, m)
,其中 $n$ 是机器人个数,$m$ 是工厂个数。初始时,所有元素置为 -1。
4.调用递归函数 process1(robot, factory, n-1, m-1, dp)
计算最小总距离。
--1.如果机器人已经全部处理完毕(即 i < 0
),返回 0。
--2.如果已经没有可用的工厂(即 j < 0
),返回最大整数值(表示当前状态不合法,无解)。
--3.如果 dp[i][j]
已经计算过了,直接返回这个值。
--4 定义变量 ans
表示当前状态下的最小距离,初始化为左边一个工厂的最小距离。然后遍历当前工厂能够维修的机器人,计算这些机器人到当前工厂的距离,并且调用递归函数 process1
计算剩余机器人和工厂的最小距离。
--5.在所有可能的状态中选择一个距离最小的状态,并返回这个距离。
5.返回递归函数 process1
的计算结果。
时间复杂度:O((n ^ m)m),其中 n 是机器人个数,m 是工厂个数。
空间复杂度:O(nm)。
算法2:
1.首先对机器人位置数组 robot
进行排序,按照从小到大的顺序排列。
2.对工厂位置数组 factory
按照第一个元素排序,也就是按照工厂所在的位置从小到大排列。
3.创建一个二维数组 dp
,大小为 (n, m)
,其中 $n$ 是机器人个数,$m$ 是工厂个数。初始时,所有元素置为最大整数值。
4.遍历机器人和工厂,使用动态规划计算最小总距离。
--1.定义变量 ans
表示当前状态下的最小距离,初始化为左边一个工厂的最小距离。
--2.定义变量 distance
表示当前机器人到当前工厂的距离,初始化为 0。
--3.遍历当前工厂能够维修的机器人,计算这些机器人到当前工厂的距离,并且查找剩余机器人和工厂的最小距离。
--4.更新变量 ans
和 distance
。
--5.在所有可能的状态中选择一个距离最小的状态,并将这个距离赋值给当前状态。
5.返回 dp[n-1][m-1]
,即机器人全部处理完毕时到达最后一个工厂所需要的最小总距离。
算法2时间复杂度:O(n(m ^ 2)),其中 n 是机器人个数,m 是工厂个数。
空间复杂度:O(nm)。
算法3:
1.首先对机器人位置数组 robot
进行排序,按照从小到大的顺序排列。
2.对工厂位置数组 factory
按照第一个元素排序,也就是按照工厂所在的位置从小到大排列。
3.创建一个二维数组 dp
,大小为 (n, m)
,其中 $n$ 是机器人个数,$m$ 是工厂个数。初始时,所有元素置为最大整数值。
4.创建一个双端队列 deque
,用于维护每个工厂能够维修的机器人的最小距离。
5.遍历工厂,对于每个工厂,使用动态规划计算最小总距离。
--1.定义变量 add
表示当前机器人到当前工厂之前的距离和,初始化为 0。
--2.定义变量 limit
表示当前工厂能够维修的机器人数量限制。
--3.初始化双端队列 deque
,将 (i, 0)
加入队列。其中 $i$ 表示机器人的下标,0 表示到达当前工厂之前的距离和为 0。
--4.遍历机器人,计算当前状态下的最小距离。
----1.如果左边有一个工厂,选择它作为当前状态的备选值。
----2.从队列中取出所有与当前机器人距离小于等于 limit
的机器人,并计算这些机器人到当前工厂的距离和。如果队列为空,则跳过该步骤。
----3.在所有可能的状态中选择一个距离最小的状态,并将这个距离赋值给当前状态。
----4.将当前机器人加入队列,更新队列中的元素。
--5.返回 dp[n-1][m-1]
,即机器人全部处理完毕时到达最后一个工厂所需要的最小总距离。
6.返回 dp[n-1][m-1]
,即机器人全部处理完毕时到达最后一个工厂所需要的最小总距离。
时间复杂度:O(nm log n),其中 n 是机器人个数,m 是工厂个数。
空间复杂度:O(nm)。
go三种算法完整代码如下:
package main
import (
"fmt"
"math"
"sort"
)
func minimumTotalDistance1(robot []int, factory [][]int) int64 {
n := len(robot)
m := len(factory)
sort.Ints(robot)
sortFactoryByFirst(factory)
dp := make([][]int64, n)
for i := range dp {
dp[i] = make([]int64, m)
for j := range dp[i] {
dp[i][j] = -1
}
}
return process1(robot, factory, n-1, m-1, dp)
}
func process1(robot []int, factory [][]int, i, j int, dp [][]int64) int64 {
if i < 0 {
return 0
}
if j < 0 {
return math.MaxInt64
}
if dp[i][j] != -1 {
return dp[i][j]
}
ans := process1(robot, factory, i, j-1, dp)
distance := int64(0)
for l, num := i, 1; l >= 0 && num <= factory[j][1]; l, num = l-1, num+1 {
curAns := process1(robot, factory, l-1, j-1, dp)
d := int64(abs(robot[l] - factory[j][0]))
distance += d
if curAns != math.MaxInt64 {
ans = min(ans, curAns+distance)
}
}
dp[i][j] = ans
return ans
}
func sortFactoryByFirst(a [][]int) {
sort.Slice(a, func(i, j int) bool {
return a[i][0] < a[j][0]
})
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
func min(a, b int64) int64 {
if a < b {
return a
}
return b
}
func minimumTotalDistance2(robot []int, factory [][]int) int64 {
n := len(robot)
m := len(factory)
sort.Ints(robot)
sortFactoryByFirst(factory)
dp := make([][]int64, n)
for i := 0; i < n; i++ {
dp[i] = make([]int64, m)
for j := 0; j < m; j++ {
ans := int64(math.MaxInt64)
if j > 0 {
ans = dp[i][j-1]
}
distance := int64(0)
for l, num := i, 1; l >= 0 && num <= factory[j][1]; l, num = l-1, num+1 {
curAns := int64(0)
if l-1 < 0 {
curAns = 0
} else if j-1 < 0 {
curAns = math.MaxInt64
} else {
curAns = dp[l-1][j-1]
}
distance += int64(abs(robot[l] - factory[j][0]))
if curAns != math.MaxInt64 {
ans = min(ans, curAns+distance)
}
}
dp[i][j] = ans
}
}
return dp[n-1][m-1]
}
func minimumTotalDistance3(robot []int, factory [][]int) int64 {
n := len(robot)
m := len(factory)
sort.Ints(robot)
sortFactoryByFirst(factory)
dp := make([][]int64, n)
for i := 0; i < n; i++ {
dp[i] = make([]int64, m)
for j := 0; j < m; j++ {
dp[i][j] = math.MaxInt64
}
}
deque := make([][]int64, n+1)
for i := 0; i < n+1; i++ {
deque[i] = make([]int64, 2)
}
var l, r int
for j := 0; j < m; j++ {
add := int64(0)
limit := int64(factory[j][1])
l = 0
r = 1
deque[l][0] = -1
deque[l][1] = 0
for i := 0; i < n; i++ {
p1 := int64(math.MaxInt64)
if j > 0 {
p1 = dp[i][j-1]
}
add += int64(abs(robot[i] - factory[j][0]))
if deque[l][0] == int64(i)-limit-1 {
l++
}
p2 := int64(math.MaxInt64)
if l < r {
best := deque[l][1]
if best != math.MaxInt64 {
p2 = add + best
}
}
dp[i][j] = min(p1, p2)
fill := p1
if p1 == math.MaxInt64 {
fill = p1
} else {
fill = p1 - add
}
for l < r && deque[r-1][1] >= fill {
r--
}
deque[r][0] = int64(i)
deque[r][1] = fill
r++
}
}
return dp[n-1][m-1]
}
func main() {
if true {
robot := []int{0, 4, 6}
factory := [][]int{{2, 2}, {6, 2}}
fmt.Println(minimumTotalDistance1(robot, factory))
}
if true {
robot := []int{0, 4, 6}
factory := [][]int{{2, 2}, {6, 2}}
fmt.Println(minimumTotalDistance2(robot, factory))
}
if true {
robot := []int{0, 4, 6}
factory := [][]int{{2, 2}, {6, 2}}
fmt.Println(minimumTotalDistance3(robot, factory))
}
}
rust第2种和第3种算法代码如下:
fn minimum_total_distance2(robot: Vec<i32>, factory: Vec<Vec<i32>>) -> i64 {
let n = robot.len();
let m = factory.len();
// 排序操作
let mut sorted_robot = robot.clone();
sorted_robot.sort_unstable();
let mut sorted_factory = factory.clone();
sorted_factory.sort_unstable_by_key(|a| a[0]);
let mut dp = vec![vec![std::i64::MAX; m]; n];
for i in 0..n {
for j in 0..m {
// ans = dp[i][j - 1] -> 0...i -> 0...j-1
let mut ans = std::i64::MAX;
if j >= 1 {
ans = dp[i][j - 1];
}
let mut distance = 0;
for (l, num) in (0..=i).rev().zip(1..=factory[j][1]) {
let cur_ans = if l == 0 {
0
} else if j == 0 {
std::i64::MAX
} else {
dp[l - 1][j - 1]
};
let d = (robot[l] - factory[j][0]).abs() as i64;
distance += d;
if cur_ans != std::i64::MAX {
ans = ans.min(cur_ans + distance);
}
}
dp[i][j] = ans;
}
}
dp[n - 1][m - 1]
}
fn minimum_total_distance3(robot: Vec<i32>, factory: Vec<Vec<i32>>) -> i64 {
let n = robot.len();
let m = factory.len();
// 排序操作
let mut sorted_robot = robot.clone();
sorted_robot.sort_unstable();
let mut sorted_factory = factory.clone();
sorted_factory.sort_unstable_by_key(|a| a[0]);
let mut dp = vec![vec![std::i64::MAX; m]; n];
for j in 0..m {
let mut add = 0;
let limit = factory[j][1] as usize;
let mut l = 0;
let mut r = 1;
let mut deque = vec![vec![0; 2]; n + 1];
deque[l][0] = std::i64::MAX;
deque[l][1] = 0;
for i in 0..n {
let p1 = if j >= 1 { dp[i][j - 1] } else { std::i64::MAX };
add += (sorted_robot[i] - sorted_factory[j][0]).abs() as i64;
while l < r && deque[l][0] == i as i64 - limit as i64 - 1 {
l += 1;
}
let p2 = if l < r && deque[l][1] != std::i64::MAX {
add + deque[l][1]
} else {
std::i64::MAX
};
dp[i][j] = p1.min(p2);
let fill = if p1 == std::i64::MAX { p1 } else { p1 - add };
while l < r && deque[r - 1][1] >= fill {
r -= 1;
}
deque[r][0] = i as i64;
deque[r][1] = fill;
r += 1;
}
}
dp[n - 1][m - 1]
}
fn main() {
let robot = vec![0, 4, 6];
let factory = vec![vec![2, 2], vec![6, 2]];
println!(
"{}",
minimum_total_distance2(robot.clone(), factory.clone())
);
println!(
"{}",
minimum_total_distance3(robot.clone(), factory.clone())
);
}
c++三种算法完整代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
struct Pair {
int x, y;
};
void sortFactoryByFirst(vector<vector<int>>& factory) {
sort(factory.begin(), factory.end(), [](const auto& a, const auto& b) {
return a[0] < b[0];
});
}
int64_t minimumTotalDistance1(vector<int>& robot, vector<vector<int>>& factory, int n, int m, vector<vector<int64_t>>& dp) {
if (n < 0) {
return 0;
}
if (m < 0) {
return INT64_MAX;
}
if (dp[n][m] != -1) {
return dp[n][m];
}
int64_t ans = minimumTotalDistance1(robot, factory, n, m - 1, dp);
int64_t distance = 0;
for (int l = n, num = 1; l >= 0 && num <= factory[m][1]; l--, num++) {
int64_t curAns = minimumTotalDistance1(robot, factory, l - 1, m - 1, dp);
int64_t d = abs(robot[l] - factory[m][0]);
distance += d;
if (curAns != INT64_MAX) {
ans = min(ans, curAns + distance);
}
}
dp[n][m] = ans;
return ans;
}
int64_t minimumTotalDistance2(vector<int>& robot, vector<vector<int>>& factory, int n, int m) {
sort(robot.begin(), robot.end());
sortFactoryByFirst(factory);
vector<vector<int64_t>> dp(n, vector<int64_t>(m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int64_t ans = INT64_MAX;
if (j > 0) {
ans = dp[i][j - 1];
}
int64_t distance = 0;
for (int l = i, num = 1; l >= 0 && num <= factory[j][1]; l--, num++) {
int64_t curAns = 0;
if (l - 1 < 0) {
curAns = 0;
}
else if (j - 1 < 0) {
curAns = INT64_MAX;
}
else {
curAns = dp[l - 1][j - 1];
}
distance += abs(robot[l] - factory[j][0]);
if (curAns != INT64_MAX) {
ans = min(ans, curAns + distance);
}
}
dp[i][j] = ans;
}
}
return dp[n - 1][m - 1];
}
int64_t minimumTotalDistance3(vector<int>& robot, vector<vector<int>>& factory, int n, int m) {
sort(robot.begin(), robot.end());
sortFactoryByFirst(factory);
vector<vector<int64_t>> dp(n, vector<int64_t>(m, INT64_MAX));
vector<Pair> deque(n + 1);
int l = 0, r = 1;
deque[0].x = -1;
deque[0].y = 0;
for (int j = 0; j < m; j++) {
int64_t add = 0;
int64_t limit = (int64_t)factory[j][1];
l = 0;
r = 1;
deque[l].x = -1;
deque[l].y = 0;
for (int i = 0; i < n; i++) {
int64_t p1 = INT64_MAX;
if (j > 0) {
p1 = dp[i][j - 1];
}
add += abs(robot[i] - factory[j][0]);
while (l < r && deque[l].x == (int64_t)i - limit - 1) {
l++;
}
int64_t p2 = INT64_MAX;
if (l < r) {
int64_t best = deque[l].y;
if (best != INT64_MAX) {
p2 = add + best;
}
}
dp[i][j] = min(p1, p2);
int64_t fill = p1;
if (p1 == INT64_MAX) {
fill = p1;
}
else {
fill = p1 - add;
}
while (l < r && deque[r - 1].y >= fill) {
r--;
}
deque[r].x = i;
deque[r].y = fill;
r++;
}
}
return dp[n - 1][m - 1];
}
int main() {
if (true) {
vector<int> robot{ 0, 4, 6 };
vector<vector<int>> factory{ {2, 2}, {6, 2} };
int n = robot.size();
int m = factory.size();
vector<vector<int64_t>> dp(n, vector<int64_t>(m, -1));
printf("%lld\n", minimumTotalDistance1(robot, factory, n - 1, m - 1, dp));
}
if (true) {
vector<int> robot{ 0, 4, 6 };
vector<vector<int>> factory{ {2, 2}, {6, 2} };
int n = robot.size();
int m = factory.size();
printf("%lld\n", minimumTotalDistance2(robot, factory, n, m));
}
if (true) {
vector<int> robot{ 0, 4, 6 };
vector<vector<int>> factory{ {2, 2}, {6, 2} };
int n = robot.size();
int m = factory.size();
printf("%lld\n", minimumTotalDistance3(robot, factory, n, m));
}
return 0;
}
c语言的不好写,故没有代码。
2023-05-06:X轴上有一些机器人和工厂。给你一个整数数组robot,其中robot[i]是第i个机器人的位置 再给你一个二维整数数组factory,其中 factory[j] = [posit的更多相关文章
- Task 4.4二维环形数组求最大子矩阵之和
任务: (1)输入一个二维整形数组,数组里有正数也有负数. (2)二维数组首尾相接,象个一条首尾相接带子一样. (3)数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. (4)求所有子数 ...
- 子串查询(二维前缀数组) 2018"百度之星"程序设计大赛 - 资格赛
子串查询 Time Limit: 3500/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Subm ...
- PHP二维关联数组的遍历方式
采用foreach循环对二维索引数组进行遍历,相对来讲速度更快,效率更高,foreach循环是PHP中专门用来循环数组的.实例也相对简单,多加练习,想清楚程序运行逻辑即可. <?php $arr ...
- C++ 指针二维数组, C++二维指针数组笔记
C++ 二维动态数组 一. 已知第一维 #include <iostream> using namespace std; int main(int argc, char const *ar ...
- 分配一维动态数组or 二维动态数组的方法以及学习 new 方法or vector
先来个开胃菜 // 使用new动态分配存储空间 #include<iostream> using std::cout; int main() { // 第1种方式 int *a=new i ...
- 计算机二级-C语言-程序填空题-190109记录-对二维字符串数组的处理
//给定程序,函数fun的功能是:求出形参ss所指字符串数组中最长字符串的长度,将其余字符串右边用字符*补齐,使其与最长的字符串等长.ss所指字符串数组中共有M个字符串,且串长<N. //重难点 ...
- 二维字符数组利用gets()函数输入
举例: ][]; ;i<;i++) gets(a[i]); a是二维字符数组的数组名,相当于一维数组的指针, 所以a[i]就相当于指向第i个数组的指针,类型就相当于char *,相当于字符串.
- go 动态数组 二维动态数组
go使用动态数组还有点麻烦,比python麻烦一点,需要先定义. 动态数组申明 var dynaArr []string 动态数组添加成员 dynaArr = append(dynaArr, &quo ...
- 【C/C++】二维数组的传参的方法/二维字符数组的声明,使用,输入,传参
[问题] 定义了一个子函数,传参的内容是一个二维数组 编译提示错误 因为多维数组作为形参传入时,必须声明除第一位维外的确定值,否则系统无法编译(算不出偏移地址) [二维数组的传参] 方法一:形参为二维 ...
- 求一个二维整数数组最大子数组之和,时间复杂度为N^2
本随笔只由于时间原因,我就只写写思想了 二维数组最大子数组之和,可以 引用 一维最大子数组之和 的思想一维最大子数组之和 的思想,在本博客上有,这里就不做多的介绍了 我们有一个最初的二维数组a[n ...
随机推荐
- vue再请求头加token
Vue:全局拦截所有请求,并在请求头中添加token - 道祖且长 - 博客园 (cnblogs.com) util.js export function sessionSet(user){ let ...
- Apache Ranger系列七:Hive 和 Spark 执行过程中的文件路径配置
背景:在使用Ranger鉴权的过程中,要求必须开启impersonation功能(即执行用户与提交用户保持一致,而不是统一代理的hive/spark).但是在执行的过程中,会需要在hdfs存储临时的文 ...
- c# Visual Studio|There is no editor available for ***,make sure the application for the file type(.vb) is installed问题解决方法
这个问题出现在在使用VS编码当中,电脑意外关机,导致的文件的缺失或者损坏. 使用反编译软件(如:ILSpy)对编译后的 .EXE文件进行反编译,在翻遍的结果中将相关代码拷贝至目标路径下,替换所需文件. ...
- linux 安装配置redis
linux 安装配置redis 安装 官网下载地址:https://redis.io/download linux下载命令:wget http://download.redis.io/releases ...
- FastReport OpenSource发布到Linux上的准备
一.安装libgdiplus(libgdiplus是一个Mono库,用于对非Windows操作系统提供GDI+兼容的API) apt-get install build-essential lib ...
- 【LeetCode回溯算法#06】复原IP地址详解(练习如何处理边界条件,判断IP合法性)
复原IP地址 力扣题目链接(opens new window) 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 ...
- Web For Pentester File include
File include(文件包含) Example 1 没有任何过滤 审计源码 没有对我们传参的page进行任何过滤,payload如下 http://172.16.1.104/fileincl/e ...
- burpsuite 设置文字大小、抓取https数据头
设置文字大小 burpsuite安装好后,有些时候文字非常的小,看的眼睛直接痛死. 找到 User options -> Display 其中 User Interface -> Font ...
- salesforce零基础学习(一百二十七)Custom Metadata Type 篇二
本篇参考: salesforce零基础学习(一百一十一)custom metadata type数据获取方式更新 https://developer.salesforce.com/docs/atlas ...
- 基于 RocketMQ Connect 构建数据流转处理平台
本文作者:周波,阿里云智能高级开发工程师, Apache RocketMQ Committer . 01 从问题中来的RocketMQ Connect 在电商系统.金融系统及物流系统,我们经常可以看到 ...