2024华为OD试题及答案-A042-微服务的集成测试

题目描述

现在有n个容器服务,服务的启动可能有一定的依赖性(有些服务启动没有依赖),其次服务自身启动加载会消耗一些时间。

给你一个 n x n 的二维矩阵useTime,其中

  • useTime[i][i]=10 表示服务i自身启动加载需要消耗10s
  • useTime[i][j] = 1 表示服务i启动依赖服务j启动完成
  • useTime[i][k]=0  表示服务i启动不依赖服务k

其实 0<= i,j,k < n。

服务之间启动没有循环依赖(不会出现环),若想对任意一个服务i进行集成测试(服务i自身也需要加载),求最少需要等待多少时间。

输入描述

第一行输入服务总量 n,
之后的 n 行表示服务启动的依赖关系以及自身启动加载耗时
最后输入 k 表示计算需要等待多少时间后可以对服务 k 进行集成测试

其中 1 <= k <=n,1<=n<=100

输出描述

最少需要等待多少时间(s)后可以对服务 k 进行集成测试

用例
输入3
5 0 0
1 5 0
0 1 5
3
输出15
说明服务3启动依赖服务2,服务2启动依赖服务1,由于服务1,2,3自身加载需要消耗5s,所以5+5+5=15,需要等待15s后可以对服务3进行集成测试
输入3
5 0 0
1 10 1
1 0 11
2
输出26
说明服务2启动依赖服务1和服务3,服务3启动需要依赖服务1,服务1,2,3自身加载需要消耗5s,10s,11s,所以5+10+11=26s,需要等待26s后可以对服务2进行集成测试。
输入4
2 0 0 0
0 3 0 0
1 1 4 0
1 1 1 5
4
输出12
说明服务3启动依赖服务1和服务2,服务4启动需要依赖服务1,2,3,服务1,2,3自身加载需要消耗2s,3s,4s,5s,所以3+4+5=12s(因为服务1和服务2可以同时启动),要等待12s后可以对服务4进行集成测试。
输入5
1 0 0 0 0
0 2 0 0 0
1 1 3 0 0
1 1 0 4 0
0 0 1 1 5
5
输出11
说明服务3启动依赖服务1和服务2,服务4启动需要依赖服务1,2,服务5启动需要依赖服务3,5,服务1,2,3,4,5自身加载需要消耗1s,2s,3s,4s,5s,所以2+4+5=11s(因为服务1和服务2可以同时启动,服务3和服务4可以同时启动),要等待11s后可以对服务5进行集成测试。

解题思路分析

题目要求计算启动某个服务及其依赖的最少时间。可以将这个问题看作一个带权图中的最短路径问题。这里每个服务节点代表一个顶点,依赖关系代表边,边的权重是启动时间。

  1. 输入描述

    • 第一行:服务总量n
    • 接下来的n行:表示服务启动的依赖关系及自身启动加载耗时。
    • 最后一行:需要计算的服务编号k
  2. 输出描述

    • 最少需要等待多少时间(秒)可以对服务k进行集成测试。

解题步骤:

  1. 建图

    • 使用一个二维数组useTime表示图中的边权重。
  2. 最短路径算法

    • 使用拓扑排序(无环图的特点)来计算从起始服务到目标服务的最短路径。
    • 对于每个服务i,如果有依赖服务j,则useTime[i][j]表示依赖的时间。
    • 使用动态规划(DP)来计算从每个服务到目标服务的最短时间。

C++程序实现

 
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

int findMinTime(int n, vector<vector<int>>& useTime, int k) {
    vector<int> dp(n, INT_MAX);
    dp[k] = 10; // 因为服务k自身启动需要10s
    
    // 拓扑排序计算最长路径
    queue<int> q;
    vector<int> inDegree(n, 0);
    
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (useTime[i][j] == 1) {
                inDegree[j]++;
            }
        }
    }
    
    for (int i = 0; i < n; ++i) {
        if (inDegree[i] == 0) {
            q.push(i);
            if (i != k) {
                dp[i] = 0;
            }
        }
    }
    
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        
        for (int v = 0; v < n; ++v) {
            if (useTime[u][v] == 1) {
                dp[v] = min(dp[v], dp[u] + 10);
                if (--inDegree[v] == 0) {
                    q.push(v);
                }
            }
        }
    }
    
    return dp[k];
}

int main() {
    int n;
    cin >> n;
    vector<vector<int>> useTime(n, vector<int>(n));
    
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> useTime[i][j];
        }
    }
    
    int k;
    cin >> k;
    k--; // 转换为0索引
    
    int result = findMinTime(n, useTime, k);
    cout << result << endl;
    
    return 0;
}

Python程序实现

 
from collections import deque
import sys

def find_min_time(n, use_time, k):
    dp = [sys.maxsize] * n
    dp[k] = 10  # 因为服务k自身启动需要10s

    # 拓扑排序计算最长路径
    q = deque()
    in_degree = [0] * n
    
    for i in range(n):
        for j in range(n):
            if use_time[i][j] == 1:
                in_degree[j] += 1
    
    for i in range(n):
        if in_degree[i] == 0:
            q.append(i)
            if i != k:
                dp[i] = 0
    
    while q:
        u = q.popleft()
        
        for v in range(n):
            if use_time[u][v] == 1:
                dp[v] = min(dp[v], dp[u] + 10)
                in_degree[v] -= 1
                if in_degree[v] == 0:
                    q.append(v)
    
    return dp[k]

# 输入
n = int(input().strip())
use_time = []
for _ in range(n):
    use_time.append(list(map(int, input().strip().split())))
k = int(input().strip()) - 1  # 转换为0索引

# 计算并输出结果
result = find_min_time(n, use_time, k)
print(result)

解释

上述代码中,使用拓扑排序来处理服务启动的依赖关系。通过队列和入度数组来管理图的遍历顺序,并使用动态规划数组dp记录到达每个服务节点的最短时间。通过逐步更新dp数组,最终得到目标服务的最短启动时间。C++和Python实现的逻辑一致,只是语法有所不同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值