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.更新变量 ansdistance

--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的更多相关文章

  1. Task 4.4二维环形数组求最大子矩阵之和

    任务: (1)输入一个二维整形数组,数组里有正数也有负数. (2)二维数组首尾相接,象个一条首尾相接带子一样. (3)数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. (4)求所有子数 ...

  2. 子串查询(二维前缀数组) 2018"百度之星"程序设计大赛 - 资格赛

    子串查询 Time Limit: 3500/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Subm ...

  3. PHP二维关联数组的遍历方式

    采用foreach循环对二维索引数组进行遍历,相对来讲速度更快,效率更高,foreach循环是PHP中专门用来循环数组的.实例也相对简单,多加练习,想清楚程序运行逻辑即可. <?php $arr ...

  4. C++ 指针二维数组, C++二维指针数组笔记

    C++ 二维动态数组 一. 已知第一维 #include <iostream> using namespace std; int main(int argc, char const *ar ...

  5. 分配一维动态数组or 二维动态数组的方法以及学习 new 方法or vector

    先来个开胃菜 // 使用new动态分配存储空间 #include<iostream> using std::cout; int main() { // 第1种方式 int *a=new i ...

  6. 计算机二级-C语言-程序填空题-190109记录-对二维字符串数组的处理

    //给定程序,函数fun的功能是:求出形参ss所指字符串数组中最长字符串的长度,将其余字符串右边用字符*补齐,使其与最长的字符串等长.ss所指字符串数组中共有M个字符串,且串长<N. //重难点 ...

  7. 二维字符数组利用gets()函数输入

    举例: ][]; ;i<;i++) gets(a[i]); a是二维字符数组的数组名,相当于一维数组的指针, 所以a[i]就相当于指向第i个数组的指针,类型就相当于char *,相当于字符串.

  8. go 动态数组 二维动态数组

    go使用动态数组还有点麻烦,比python麻烦一点,需要先定义. 动态数组申明 var dynaArr []string 动态数组添加成员 dynaArr = append(dynaArr, &quo ...

  9. 【C/C++】二维数组的传参的方法/二维字符数组的声明,使用,输入,传参

    [问题] 定义了一个子函数,传参的内容是一个二维数组 编译提示错误 因为多维数组作为形参传入时,必须声明除第一位维外的确定值,否则系统无法编译(算不出偏移地址) [二维数组的传参] 方法一:形参为二维 ...

  10. 求一个二维整数数组最大子数组之和,时间复杂度为N^2

    本随笔只由于时间原因,我就只写写思想了 二维数组最大子数组之和,可以  引用  一维最大子数组之和 的思想一维最大子数组之和 的思想,在本博客上有,这里就不做多的介绍了 我们有一个最初的二维数组a[n ...

随机推荐

  1. vue再请求头加token

    Vue:全局拦截所有请求,并在请求头中添加token - 道祖且长 - 博客园 (cnblogs.com) util.js export function sessionSet(user){ let ...

  2. Apache Ranger系列七:Hive 和 Spark 执行过程中的文件路径配置

    背景:在使用Ranger鉴权的过程中,要求必须开启impersonation功能(即执行用户与提交用户保持一致,而不是统一代理的hive/spark).但是在执行的过程中,会需要在hdfs存储临时的文 ...

  3. c# Visual Studio|There is no editor available for ***,make sure the application for the file type(.vb) is installed问题解决方法

    这个问题出现在在使用VS编码当中,电脑意外关机,导致的文件的缺失或者损坏. 使用反编译软件(如:ILSpy)对编译后的 .EXE文件进行反编译,在翻遍的结果中将相关代码拷贝至目标路径下,替换所需文件. ...

  4. linux 安装配置redis

    linux 安装配置redis 安装 官网下载地址:https://redis.io/download linux下载命令:wget http://download.redis.io/releases ...

  5. FastReport OpenSource发布到Linux上的准备

    一.安装libgdiplus(libgdiplus是一个Mono库,用于对非Windows操作系统提供GDI+兼容的API)   apt-get install build-essential lib ...

  6. 【LeetCode回溯算法#06】复原IP地址详解(练习如何处理边界条件,判断IP合法性)

    复原IP地址 力扣题目链接(opens new window) 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 ...

  7. Web For Pentester File include

    File include(文件包含) Example 1 没有任何过滤 审计源码 没有对我们传参的page进行任何过滤,payload如下 http://172.16.1.104/fileincl/e ...

  8. burpsuite 设置文字大小、抓取https数据头

    设置文字大小 burpsuite安装好后,有些时候文字非常的小,看的眼睛直接痛死. 找到 User options -> Display 其中 User Interface -> Font ...

  9. salesforce零基础学习(一百二十七)Custom Metadata Type 篇二

    本篇参考: salesforce零基础学习(一百一十一)custom metadata type数据获取方式更新 https://developer.salesforce.com/docs/atlas ...

  10. 基于 RocketMQ Connect 构建数据流转处理平台

    本文作者:周波,阿里云智能高级开发工程师, Apache RocketMQ Committer . 01 从问题中来的RocketMQ Connect 在电商系统.金融系统及物流系统,我们经常可以看到 ...