2023-10-18:用go语言,给定一个数组arr,长度为n,表示有0~n-1号设备,

arr[i]表示i号设备的型号,型号的种类从0~k-1,一共k种型号,

给定一个k*k的矩阵map,来表示型号之间的兼容情况,

map[a][b] == 1,表示a型号兼容b型号,

map[a][b] == 0,表示a型号不兼容b型号,

兼容关系是有向图,也就是a型号兼容b型号,不代表b型号同时兼容a型号,

如果i设备的型号兼容j设备的型号,那么可以从i设备修建一条去往j设备的线路,

修建线路的代价是i设备到j设备的距离:|i-j|,

你的目标是从0号设备到达n-1号设备,并不一定每个设备都联通,只需要到达即可。

返回最小的修建代价,如果就是无法到达返回-1。

1 <= n <= 1000,

1 <= k <= 50。

来自招商银行。

来自左程云

答案2023-10-18:

大体步骤:

1.创建一个二维切片 own,长度为 k,用于记录每个型号的设备编号。

2.创建一个二维切片 nexts,长度为 k,用于记录每个型号兼容的下一个型号。

3.遍历数组 arr,将每个设备的编号添加到对应型号的 own 中。

4.遍历兼容矩阵 m,将每个型号兼容的下一个型号添加到对应型号的 nexts 中。

5.创建一个二叉堆 heap,并定义排序函数,按照修建代价升序排列。

6.将起始设备 (0, 0) 添加到堆中,表示从 0 号设备开始,修建代价为 0。

7.创建一个长度为 n 的布尔型切片 visited,用于标记设备是否被访问过。

8.当堆不为空时,进行以下操作:

  • 弹出堆顶元素 t,表示当前位置和当前的修建代价。

  • 获取当前位置 cur 的设备编号和修建代价。

  • 如果当前位置为目标位置 n-1,则返回当前的修建代价。

  • 将当前位置标记为已访问。

9.获取当前设备的型号 model

10.遍历下一个兼容的型号 nextModel,以及拥有下一个型号 nextModel 的设备位置 nextPosition

 - 如果设备位置未被访问过,则将 `(nextPosition, cost + abs(nextPosition, position))` 添加到堆中。

11.如果无法到达目标位置,返回 -1。

12.在 main 函数中调用 minCost 函数,并输出结果。

总的时间复杂度为 $O(nk^2logn)$,其中 n 是设备数量,k 是型号数量。遍历拥有型号的设备位置的过程复杂度为 O(n),堆操作的复杂度为 O(logn),遍历所有可能的型号和设备位置的复杂度为 $O(k^2$),所以总的时间复杂度为 $O(nk^2logn)$。

总的额外空间复杂度为 O(n),其中 n 是设备数量。需要额外的空间来存储 ownnextsvisited 和堆 heap,它们的空间复杂度都为 O(n)。

go完整代码如下:

package main

import (
"fmt" "github.com/emirpasic/gods/trees/binaryheap"
) func minCost(arr []int, m [][]int, n int, k int) int {
// 0 : {4,7,13,26}
// 1 : {5,45,3,17}
own := make([][]int, k)
nexts := make([][]int, k)
for i := 0; i < k; i++ {
own[i] = []int{}
nexts[i] = []int{}
} for i := 0; i < n; i++ {
own[arr[i]] = append(own[arr[i]], i)
} for i := 0; i < k; i++ {
for j := 0; j < k; j++ {
if m[i][j] == 1 {
nexts[i] = append(nexts[i], j)
}
}
} heap := binaryheap.NewWith(func(a, b interface{}) int {
return a.([]int)[1] - b.([]int)[1]
})
heap.Push([]int{0, 0}) visited := make([]bool, n) for heap.Size() > 0 {
t, _ := heap.Pop()
cur := t.([]int)
position := cur[0]
cost := cur[1] if !visited[position] {
visited[position] = true if position == n-1 {
return cost
} model := arr[position] for _, nextModel := range nexts[model] {
for _, nextPosition := range own[nextModel] {
if !visited[nextPosition] {
heap.Push([]int{nextPosition, cost + abs(nextPosition, position)})
}
}
}
}
} return -1
} func abs(a, b int) int {
if a-b < 0 {
return b - a
}
return a - b
} func main() {
arr := []int{0, 1, 2, 3}
m := [][]int{{0, 1, 0, 1, 0}, {1, 0, 1, 1, 0}, {2, 1, 1, 1, 1}, {3, 0, 0, 0, 0}}
n := 4
k := 4
result := minCost(arr, m, n, k)
fmt.Println(result)
}

rust完整代码如下:

use std::cmp::Reverse;
use std::collections::BinaryHeap; fn min_cost(arr: &[i32], map: &[Vec<i32>], n: usize, k: usize) -> i32 {
let mut own: Vec<Vec<i32>> = vec![Vec::new(); k];
let mut nexts: Vec<Vec<i32>> = vec![Vec::new(); k]; for (i, &value) in arr.iter().enumerate() {
own[value as usize].push(i as i32);
} for (i, row) in map.iter().enumerate() {
for (j, &value) in row.iter().enumerate() {
if value == 1 {
nexts[i as usize].push(j as i32);
}
}
} let mut heap: BinaryHeap<(i32, i32)> = BinaryHeap::new();
heap.push((0, 0));
let mut visited: Vec<bool> = vec![false; n]; while let Some((position, cost)) = heap.pop() {
let position = position as usize;
let cost = cost; if !visited[position] {
visited[position] = true; if position == n - 1 {
return cost;
} let model = arr[position] as usize; for &next_model in &nexts[model] {
for &next_position in &own[next_model as usize] {
if !visited[next_position as usize] {
heap.push((
next_position,
cost + (next_position - position as i32).abs(),
));
}
}
}
}
} -1
} fn main() {
let arr = [0, 1, 2, 3];
let m = [
vec![0, 1, 0, 1, 0],
vec![1, 0, 1, 1, 0],
vec![2, 1, 1, 1, 1],
vec![3, 0, 0, 0, 0],
];
let n = 4;
let k = 4; let result = min_cost(&arr, &m, n, k);
println!("Minimum Cost: {}", result);
}

c++完整代码如下:

#include <iostream>
#include <queue>
#include <vector>
#include <cmath> using namespace std; int minCost(vector<int>& arr, vector<vector<int>>& map, int n, int k) {
vector<vector<int>> own(k);
vector<vector<int>> nexts(k);
for (int i = 0; i < n; i++) {
own[arr[i]].push_back(i);
}
for (int i = 0; i < k; i++) {
for (int j = 0; j < k; j++) {
if (map[i][j] == 1) {
nexts[i].push_back(j);
}
}
}
priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> heap;
heap.push({ 0, 0 });
vector<bool> visited(n, false);
while (!heap.empty()) {
vector<int> cur = heap.top();
heap.pop();
int position = cur[0];
int cost = cur[1];
if (!visited[position]) {
visited[position] = true;
if (position == n - 1) {
return cost;
}
int model = arr[position];
for (int nextModel : nexts[model]) {
for (int nextPosition : own[nextModel]) {
if (!visited[nextPosition]) {
heap.push({ nextPosition, cost + abs(nextPosition - position) });
}
}
}
}
}
return -1;
} int main() {
vector<int> arr = { 0, 1, 2, 3 };
vector<vector<int>> m = { {0, 1, 0, 1, 0}, {1, 0, 1, 1, 0}, {2, 1, 1, 1, 1}, {3, 0, 0, 0, 0} };
int n = 4;
int k = 4; int result = minCost(arr, m, n, k);
cout << result << endl; return 0;
}

2023-10-18:用go语言,给定一个数组arr,长度为n,表示有0~n-1号设备, arr[i]表示i号设备的型号,型号的种类从0~k-1,一共k种型号, 给定一个k*k的矩阵map,来表示型号的更多相关文章

  1. delphi 判断一个数组的长度用 Length 还是 SizeOf ?

    判断一个数组的长度用 Length 还是 SizeOf ?最近发现一些代码, 甚至有一些专家代码, 在遍历数组时所用的数组长度竟然是 SizeOf(arr); 这不合适! 如果是一维数组.且元素大小是 ...

  2. java 一个数组的长度

    package java03; /* *如何获取数组长度 : * 格式: * 数组名称.length * * 这会得到一个int数字,代表数组的长度 * * 数组一旦创建,程序运行期间,长度不可改变 ...

  3. 判断一个数组的长度用 Length 还是 SizeOf ?

    最近发现一些代码, 甚至有一些专家代码, 在遍历数组时所用的数组长度竟然是 SizeOf(arr); 这不合适! 如果是一维数组.且元素大小是一个字节, 这样用看不出错误, 譬如: var   arr ...

  4. 11-C语言指针&一维数组&字符串

    一.用指针遍历数组元素 1.最普通的遍历方式是用数组下标来遍历元素 1 // 定义一个int类型的数组 2 int a[4] = {1, 2, 3, 4}; 3 4 int i; 5 for (i = ...

  5. go语言学习--指针数组和数组指针

    数组指针(也称行指针)定义 int (*p)[n];()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长.也就是说执行p+1时,p要跨过n个整型数据的 ...

  6. 算法基础_递归_给定m个A,n个B,一共有多少种排列

    问题描述: 给定m个A,n个B,一共有多少种排列 解题源代码: /** * 给定m个A,n个B,问一共有多少种排列 * @author Administrator * */ public class ...

  7. hdu2049 不容易系列之(4)——考新郎 错排+组合 一共有N对新婚夫妇,N个新娘随机坐成一排,每个新郎只能选一个, 其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.

    不容易系列之(4)——考新郎 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  8. 位运算解决“一个数组中,只有一个数字出现n次,其他数字出现k次”问题

    转自:https://blog.csdn.net/monster_girl/article/details/52928864 在学习完位操作后,经常会遇到一类关于查找缺失整数的问题. 第一类是给你一个 ...

  9. 选取两个有序数组中最大的K个值,降序存入另一个数组中

    原题: 假设有两个有序的整型数组int *a1, int *a2,长度分别为m和n.试用C语言写出一个函数选取两个数组中最大的K个值(K可能大于m+n)写到int *a3中,保持a3降序,并返回a3实 ...

  10. Top K问题的两种解决思路

    Top K问题在数据分析中非常普遍的一个问题(在面试中也经常被问到),比如: 从20亿个数字的文本中,找出最大的前100个. 解决Top K问题有两种思路, 最直观:小顶堆(大顶堆 -> 最小1 ...

随机推荐

  1. asp.net core如何获取客户端IP地址

    客户端直接访问服务器 直接通过HttpContext.Connection.RemoteIpAddress获取客户端Ip [HttpGet] [Route("GetClientIP" ...

  2. 行行AI人才直播第8期:新加坡国立大学在读博士生张傲《多模态大语言模型(MLLM)的简介及高效训练》

    随着 ChatGPT 在各领域展现出非凡能力,多模态大型语言模型(MLLM)近来也成为了研究的热点,它利用强大的大型语言模型(LLM)作为"大脑",可以执行各种多模态任务.更让人感 ...

  3. pytest7.4版本的一个变更,可能会影响你的项目

    pytest7.4版本的一个变更,可能会影响你的项目 本文撰写于 2023.7.10 准备工作 项目结构如下 D:\Gitee\DemoRepo (17.97MB) +-- testCases (1. ...

  4. BugKu-Misc-Photo的自我修养

    下载附件 打开002文件夹,发现一张照片 看到PNG右下疑似有半个字符,怀疑PNG宽高被修改 拿到测PNG宽高的脚本 点击查看代码 import binascii import struct crcb ...

  5. ENVI大气校正方法反演Landsat 7地表温度

    本文介绍基于ENVI软件,实现对Landsat 7遥感影像加以大气校正方法的地表温度反演操作. 目录 1 图像前期处理与本文理论部分 2 实际操作 2.1 植被覆盖度计算 2.2 地表比辐射率计算 2 ...

  6. jQuery真伪数组转换

    // 真数组转伪数组 [].push.apply(obj,arr); // 伪数组转真数组 [].slice.call(obj);

  7. AB实验遇到用户不均匀怎么办?—— vivo游戏中心业务实践经验分享

    作者:vivo 互联网数据分析团队 - Li Bingchao AB实验是业务不断迭代.更新时最高效的验证方法之一:但在进行AB实验效果评估时需要特别关注"用户不均匀"的问题,稍不 ...

  8. 2023-08-04:村里面一共有 n 栋房子 我们希望通过建造水井和铺设管道来为所有房子供水。 对于每个房子 i,我们有两种可选的供水方案: 一种是直接在房子内建造水井 成本为 wells[i -

    2023-08-04:村里面一共有 n 栋房子 我们希望通过建造水井和铺设管道来为所有房子供水. 对于每个房子 i,我们有两种可选的供水方案: 一种是直接在房子内建造水井 成本为 wells[i - ...

  9. TCP如何实现可靠传输、流量控制、拥塞控制

    上一篇文章中讲述了TCP首部的存储的数据,这一篇来聊聊这些数据帮助TCP实现一些特性. 可靠传输 TCP传输会保障数据的可靠和完整,如果数据传输过程丢失了,会重新传输. 保障的第一种协议方式是 停止等 ...

  10. Protobuf vs JSON

    Protobuf(Protocol Buffers)和 JSON 都是数据序列化格式,但它们在许多方面有着显著的不同.以下是对两者的一些主要比较: 数据大小和速度: Protobuf:由于 Proto ...