首页 > 编程语言 >电脑病毒感染【华为OD机试】(JAVA&Python&C++&JS题解)

电脑病毒感染【华为OD机试】(JAVA&Python&C++&JS题解)

时间:2024-04-07 12:30:44浏览次数:73  
标签:JAVA Python 题解 电脑 节点 int 数组 dist 感染

一. 题目-电脑病毒感染

一个局域网内有很多台电脑,分别标注为0 - N-1的数字。相连接的电脑距离不一样,所以感染时间不一样,感染时间用t表示。
其中网络内一个电脑被病毒感染,其感染网络内所有的电脑需要最少需要多长时间。如果最后有电脑不会感染,则返回-1
给定一个数组times表示一个电脑把相邻电脑感染所用的时间。
如图:path[i]= {i,j, t} 表示电脑i->j 电脑i上的病毒感染j,需要时间t。

输入描述:

4
3
2 1 1
2 3 1
3 4 1
2

输出描述:

2

补充说明:

第一个参数:局域网内电脑个数N 1<=N<=200;
第二个参数:总共多少条网络连接
第三个 1 2 1 表示1->2时间为1
第七行:表示病毒最开始所在的电脑号1

收起

示例1

输入:

4
3
2 1 1
2 3 1
3 4 1
2
输出:

2

二.解题思路

这个问题可以通过使用广度优先搜索(BFS)算法来解决。以下是解题思路:

  1. 首先,建立一个字典或者列表,用于表示网络连接关系。字典的键是电脑的编号,对应的值是一个列表,列表中包含与该电脑直接相连的电脑及感染所需的时间。

  2. 初始化一个数组 target,用于存储从起始感染电脑到每个电脑的最短感染时间。将 target 初始化为正无穷大,表示初始情况下无法感染到其他电脑。将起始感染电脑的 target 设为0。

  3. 使用广度优先搜索算法遍历网络,从起始感染电脑开始,逐层感染相邻的电脑,并更新其感染时间。每次选择感染时间最短的电脑进行拓展。

  4. 最终,找到 target 数组中的最大值,即为感染网络内所有电脑所需的最短时间。如果存在无法感染到的电脑,返回-1。

这种方法保证了每个电脑被感染的顺序是按照最短感染时间进行的,从而得到最优解。在代码中,可以使用一个队列来实现广度优先搜索,同时使用一个数组来记录已经访问的电脑,以避免重复访问。

三.题解代码

Python题解代码

import sys
 
computer_nums = int(sys.stdin.readline().strip())
link_nums = int(sys.stdin.readline().strip())
network = {}
for item in range(link_nums):
    line = sys.stdin.readline().strip()
    i, j, k = list(map(int, line.split()))
    if i in network:
        network[i].append([j, k])
    else:
        network[i] = [[j, k]]
 
target = [sys.maxsize] * (computer_nums + 1)
source = int(sys.stdin.readline().strip())
target[source] = 0
compare = [source]
vd = [False] * (computer_nums + 1)
vd[source] = True
while len(compare) > 0:
    cur = compare.pop()
    vd[cur] = False
    if network.get(cur):
        for i, j in network[cur]:
            count = target[cur] + j
            if target[i] <= count:
                continue
            target[i] = count
            if vd[i]:
                continue
            vd[i] = True
            compare.append(i)
            compare.sort(key=lambda x: -target[x])
 
result = max(target[1:])
print(-1 if result == sys.maxsize else result)

JAVA题解代码

import java.util.*;

public class Main {
    static final int N = 510;  // 最大顶点数

    static class Edge {
        int next, to, weight;

        public Edge(int next, int to, int weight) {
            this.next = next;
            this.to = to;
            this.weight = weight;
        }
    }

    static int[] ne = new int[N];
    static int[] h = new int[N];
    static int[] w = new int[N];
    static int[] e = new int[N];
    static int idx;  // 邻接表表示图,ne数组表示链表中下一个节点的索引,h数组表示每个节点的链表头,w数组表示边的权值,e数组表示边的终点,idx表示当前位置

    static int[] dist = new int[N];
    static int st, n, m;  // dist数组表示从源点到各个节点的距离,st表示源点,n表示节点数,m表示边数

    static void add(int a, int b, int c) {
        // 添加一条从a到b的权值为c的边到邻接表
        ne[idx] = h[a];
        e[idx] = b;
        w[idx] = c;
        h[a] = idx++;
    }

    static int dijkstra() {
        // 使用Dijkstra算法计算单源最短路
        PriorityQueue<int[]> heap = new PriorityQueue<>(Comparator.comparingInt(arr -> arr[0]));  // 使用小顶堆作为优先队列,int[]表示整数对,arr[0]表示距离,arr[1]表示节点
        heap.offer(new int[]{0, st});  // 将源点入队,距离为0

        while (!heap.isEmpty()) {
            int[] t = heap.poll();
            int u = t[1], d = t[0];

            for (int i = h[u]; i != -1; i = ne[i]) {
                int j = e[i];

                // 如果通过u到j的距离更短
                if (dist[j] > d + w[i]) {
                    dist[j] = d + w[i];  // 更新距离
                    heap.offer(new int[]{dist[j], j});  // 将新的距离和节点加入优先队列
                }
            }
        }

        int res = 0;
        for (int i = 1; i <= n; i++) {
            res = Math.max(res, dist[i]);  // 计算最短路径中的最大值
        }

        if (res == 0x3f3f3f3f) return -1;  // 如果最终的最大距离为无穷大,说明有不可达的节点,返回-1
        return res;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();  // 读入节点数
        m = scanner.nextInt();  // 读入边数

        Arrays.fill(h, -1);  // 初始化邻接表
        Arrays.fill(dist, 0x3f3f3f3f);  // 初始化距离数组

        for (int i = 0; i < m; i++) {
            int a = scanner.nextInt(), b = scanner.nextInt(), c = scanner.nextInt();
            add(a, b, c);  // 建图,添加有向边
        }

        st = scanner.nextInt();  // 读入源点
        dist[st] = 0;
        System.out.println(dijkstra());  // 输出最短路径的最大距离
    }
}



C/C++题解代码

#include<bits/stdc++.h>
using namespace std;
int bk[205][205];
int n , m;
void init (){
    memset(bk , -1 , sizeof(bk));
    for (int i = 0 ; i <= n ; i++) bk[i][i] = 0;
}
vector<int> dijstra (int start);
void readEdge (){
    for (int i = 0; i < m; i++) {
        int x , y , z;
        cin >> x >> y >> z;
        if (bk[x][y] == -1)
            bk[x][y] = z;
        else
            bk[x][y] = min(bk[x][y] , z);
    }
}
int main() {
    cin >> n;
    cin >> m;
    init();
    readEdge();
    int start;
    cin >> start;
    vector<int> dis = dijstra(start);
    bool ok = true;
    int mx = 0;
    for (int i = 1; i <= n; i++) {
        mx = max(mx , dis[i]);
        if (dis[i] == INT_MAX) {
            ok = false;
            break;
        }
    }
    if (ok) {
        cout << mx << endl;
    } else {
        cout << -1 << endl;
    }
    return 0;
}
vector<int> dijstra (int start){
    vector<int> dis(n + 1 , INT_MAX);
    vector<bool> vis(n + 1 , false);
    dis[start] = 0;
    for (int i = 1; i <= n; i++) {
        int minn = INT_MAX;
        int u = -1;
        for (int j = 1; j <= n; j++) {
            if (!vis[j] && dis[j] < minn) {
                minn = dis[j];
                u = j;
            }
        }
        if (u == -1) break;
        vis[u] = true;
        for (int j = 1; j <= n; j++) {
            if (!vis[j] && bk[u][j] != -1 && dis[u] + bk[u][j] < dis[j]) {
                dis[j] = dis[u] + bk[u][j];
            }
        }
    }
    return dis;
}



JS题解代码

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

let n, m;
let ne, h, w, e, idx, dist;
let st;

function add(a, b, c) {
  ne[idx] = h[a];
  e[idx] = b;
  w[idx] = c;
  h[a] = idx++;
}

function dijkstra() {
  const heap = [[0, st]];
  dist[st] = 0;

  while (heap.length > 0) {
    heap.sort((a, b) => a[0] - b[0]);
    const [d, u] = heap.shift();
    if (dist[u] < d) continue;

    for (let i = h[u]; i !== -1; i = ne[i]) {
      const j = e[i];
      if (dist[j] > d + w[i]) {
        dist[j] = d + w[i];
        heap.push([dist[j], j]);
      }
    }
  }

  let res = 0;
  for (let i = 1; i <= n; i++) {
    res = Math.max(res, dist[i]);
  }

  return res === 0x3f3f3f3f ? -1 : res;
}

let lineCount = 0;

rl.on('line', (line) => {
  lineCount++;
  const parts = line.split(' ').map(Number);

  if (lineCount === 1) {
    n = parts[0];
  } else if (lineCount === 2) {
    m = parts[0];
    ne = new Array(n + 1).fill(0);
    h = new Array(n + 1).fill(-1);
    w = new Array(n + 1).fill(0);
    e = new Array(n + 1).fill(0);
    idx = 0;
    dist = new Array(n + 1).fill(0x3f3f3f3f);
  } else if (lineCount > 2 && lineCount <= m + 2) {
    add(parts[0], parts[1], parts[2]);
  } else if (lineCount === m + 3) {
    st = parts[0];
    console.log(dijkstra());
    rl.close();
  }
});




代码OJ评判结果
通过测试点

四.代码讲解(Java&Python&C++&JS分别讲解)

Python题解代码解析:

  1. 导入模块: 使用 import sys 导入 sys 模块,该模块提供了对 Python 解释器进行访问的一些变量和函数。

  2. 读取输入: 使用 sys.stdin.readline().strip() 读取标准输入,首先读取局域网内电脑的个数 computer_nums 和总共的网络连接数 link_nums

  3. 建立网络连接关系: 使用字典 network 表示电脑之间的网络连接关系。通过循环读取每一条网络连接信息,将信息添加到字典中,其中键是电脑的编号,对应的值是一个列表,列表中包含与该电脑直接相连的电脑及感染所需的时间。

  4. 初始化目标数组: 使用数组 target 表示从起始感染电脑到每个电脑的最短感染时间。将数组初始化为正无穷大,表示初始情况下无法感染到其他电脑。将起始感染电脑的目标时间设为0。

  5. 广度优先搜索: 使用广度优先搜索算法遍历网络,从起始感染电脑开始,逐层感染相邻的电脑,并更新其感染时间。通过队列 compare 记录待处理的电脑,使用数组 vd 记录已经访问的电脑,避免重复访问。

  6. 结果计算: 最终,找到 target 数组中的最大值,即为感染网络内所有电脑所需的最短时间。如果存在无法感染到的电脑,返回-1。最后输出结果。

JAVA题解代码解析:

  1. 导入包: 使用 import java.util.*; 导入 Java 中的 util 包,该包提供了各种实用工具类。

  2. 定义 Edge 类: 定义一个 Edge 类表示图的边,包括 next 表示下一个节点的索引,to 表示边的终点,weight 表示边的权值。

  3. 初始化图: 使用数组和变量初始化图的相关信息,包括 ne 数组表示链表中下一个节点的索引,h 数组表示每个节点的链表头,w 数组表示边的权值,e 数组表示边的终点,idx 表示当前位置。

  4. 添加边的方法: 定义 add 方法,用于向图中添加一条从节点 a 到节点 b 权值为 c 的边。

  5. Dijkstra算法: 定义 dijkstra 方法,使用 Dijkstra 算法计算单源最短路。使用小顶堆作为优先队列,遍历图中的节点,更新最短路径。

  6. 主函数: 在主函数中,使用 Scanner 读取输入,初始化图,并调用 dijkstra 方法计算最短路径的最大距离。输出结果。

C/C++题解代码解析:

  1. 初始化: 使用 memset 函数将 bk 数组初始化为 -1,表示初始时没有连接关系。然后使用循环将 bk 数组的对角线元素设置为0,表示自身到自身的距离为0。

  2. 读取边的信息: 使用循环读取每条边的信息,将具有最小感染时间的边信息记录到 bk 数组中。如果两台电脑之间已有边存在,保留具有最小感染时间的边。

  3. Dijkstra算法: 定义 dijkstra 函数,实现 Dijkstra 算法。在该函数中,使用优先队列和 vis 数组记录已访问的节点,更新最短路径。

  4. 主函数: 在主函数中,读取输入,初始化图,调用 dijkstra 函数计算最短路径,判断是否存在不可达的节点,并输出结果。

JS题解代码解析:

  1. 引入readline模块: 使用 const readline = require('readline'); 引入 Node.js 中的 readline 模块,该模块提供了一组接口,用于从可读流(如 process.stdin)读取数据。

  2. 初始化变量: 初始化输入、图的相关变量,包括节点数 n、边数 m、邻接表和其他辅助数组。

  3. 添加边的函数: 定义 add 函数,用于向图中添加一条从节点 a 到节点 b 权值为 c 的边。

  4. Dijkstra算法: 定义 dijkstra 函数,使用小顶堆实现 Dijkstra 算法,计算单源最短路。在该函数中,更新最短路径。

  5. 读取输入并执行算法: 使用 rl.on('line', (line) => {...}); 监听每行输入,根据输入执行相应的操作,包括初始化图、读取边的信息、调用 dijkstra 函数计算最短路径,最后输出结果。

以上代码主要涉及图的建立和最短路径算法的实现,分别使用了不同的语言特性和库来完成相应的任务。

寄语

标签:JAVA,Python,题解,电脑,节点,int,数组,dist,感染
From: https://blog.csdn.net/shrgegrb/article/details/137459352

相关文章

  • 两个字符串间的最短路径问题【华为OD机试】(JAVA&Python&C++&JS题解)
    一.题目-两个字符串间的最短路径问题给定两个字符串,分别为字符串A与字符串B。例如A字符串为ABCABBA,B字符串为CBABAC可以得到下图m*n的二维数组,定义原点为(0,0),终点为(m,n),水平与垂直的每一条边距离为1,映射成坐标系如下图。从原点(0,0)到(0,A)为水平边,距离为1,从(0,A)......
  • Python学习(八):python面向对象编程
    文章目录python面向对象编程类的定义类的实例化类的静态变量与静态方法类的静态变量类的静态方法@staticmethod类的类方法@classmethod类的继承单继承多继承多层继承类方法的重写类方法的重载调用父类的方法super函数python面向对象编程面向对象(ObjectOriented)......
  • Python学习(七):基础运算符与表达式【详解】
    文章目录python基础运算符与表达式运算符与表达式的优先级算术运算符(四则运算)算术运算符(取余/模、乘方)关系比较运算符位运算符逻辑运算符赋值运算符、复合赋值运算符条件表达式await序列切片表达式星号表达式yield表达式lambda表达式python基础运算符与表达式运算符......
  • Python量化交易系统实战--量化交易入门
    作者:麦克煎蛋  出处:https://www.cnblogs.com/mazhiyong/转载请保留这段声明,谢谢! 这个系列的文章主要是基于慕课网的量化交易学习的笔记,顺便也加了自己的一些理解和优化。一边学一边写,回头再梳理。  量化交易是指以先进的数学模型替代人为的主观判断,利用计算机技术从庞......
  • 10 Python进阶:MongoDB
    MongoDb介绍MongoDB是一个基于分布式架构的文档数据库,它使用JSON样式的数据存储,支持动态查询,完全索引。MongoDB是NoSQL数据库的一种,主要用于处理大型、半结构化或无结构化的数据。以下是MongoDB数据库的一些关键特点和优势:分布式架构:MongoDB可以运行在多个服务器上,以......
  • 基于R、Python的Copula变量相关性分析及AI大模型应用
    在工程、水文和金融等各学科的研究中,总是会遇到很多变量,研究这些相互纠缠的变量间的相关关系是各学科的研究的重点。虽然皮尔逊相关、秩相关等相关系数提供了变量间相关关系的粗略结果,但这些系数都存在着无法克服的困难。例如,皮尔逊相关系数只能反映变量间的线性相关,而秩相关则......
  • java中大型医院HIS系统源码 Angular+Nginx+SpringBoot云HIS运维平台源码
    java中大型医院HIS系统源码Angular+Nginx+SpringBoot云HIS运维平台源码云HIS系统是一款满足基层医院各类业务需要的健康云产品。该产品能帮助基层医院完成日常各类业务,提供病患预约挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医生工作站和护士工作站等一......
  • 保护你的 Java 代码:深入了解代码混淆
    在当今数字化时代,软件开发领域竞争激烈,而保护你的代码免受恶意攻击和盗用是至关重要的。代码混淆是一种常用的技术,用于增加攻击者分析和逆向工程代码的难度,从而提高代码的安全性。本文将介绍代码混淆的基本概念和详细办法,帮助你保护Java代码的安全性。1.代码混淆简介代码......
  • Java 散列码
    1.散列机制是如何工作的?2.在使用散列容器时怎样编写hashCode()和equals()方法。带有hash思想的容器,要求必须定义hashCode()。你必须为散列存储和树型存储都创建一个equals()方法,但是hashCode()只有在这个类将会被置于HashSet或者LinkedHashSet中时才是必须的。散列码是“......
  • Android Binder——Java服务注册(九)
           对于Java端使用Binder服务,主要就是注册服务和获取服务,入口都是通过ServiceManager.java中的对应方法实现。这里我们就先介绍一下Java注册Binder服务的流程。一、ServiceManager代理       无论是ServiceManager.addService()还是Service......