【2024年华为OD机试】 (B卷,100分)- 流水线(Java JS PythonC/C++)

在这里插入图片描述

一、问题描述

题目描述

一个工厂有 m 条流水线,来并行完成 n 个独立的作业,该工厂设置了一个调度系统,在安排作业时,总是优先执行处理时间最短的作业。

现给定流水线个数 m,需要完成的作业数 n,每个作业的处理时间分别为 t1, t2, ..., tn。请你编程计算处理完所有作业的耗时为多少?

n > m 时,首先处理时间短的 m 个作业进入流水线,其他的等待,当某个作业完成时,依次从剩余作业中取处理时间最短的进入处理。

输入描述

第一行为2个整数(采用空格分隔),分别表示流水线个数 m 和作业数 n

第二行输入 n 个整数(采用空格分隔),表示每个作业的处理时长 t1, t2, ..., tn

  • 0 < m, n < 100
  • 0 < t1, t2, ..., tn < 100

注:保证输入都是合法的。

输出描述

输出处理完所有作业的总时长。

用例

用例 1

输入:

3 5
8 4 3 2 10

输出:

13

题目解析

简单的逻辑题。解题思路如下:

题目说“总是优先执行处理时间最短的作业”,因此我们可以将 8 4 3 2 10 进行升序排序变为 2 3 4 8 10,然后依次将排序后元素投入对应流水线中,如下图所示:

流水线1: 2 -> 8 -> 10 (总耗时: 2 + 8 + 10 = 20)
流水线2: 3 -> 10 (总耗时: 3 + 10 = 13)
流水线3: 4 (总耗时: 4)

计算每条流水线的时间总和,最大的那个就是题解。

详细步骤

  1. 读取输入

    • 读取流水线个数 m 和作业数 n
    • 读取每个作业的处理时间 t1, t2, ..., tn
  2. 排序

    • 将作业处理时间按升序排序。
  3. 初始化流水线

    • 创建一个数组 lines,长度为 m,初始化为 0,表示每条流水线的当前总耗时。
  4. 分配作业

    • 遍历排序后的作业处理时间,依次将作业分配到当前总耗时最小的流水线中。
    • 更新该流水线的总耗时。
  5. 输出结果

    • 输出所有流水线中最大总耗时。

用例解释

用例 1
  • 输入:
    • m = 3
    • n = 5
    • t = [8, 4, 3, 2, 10]
  • 输出:
    • 13

解释

  • 排序后的作业处理时间:[2, 3, 4, 8, 10]
  • 分配作业:
    • 流水线1: 2 -> 8 -> 10 (总耗时: 2 + 8 + 10 = 20)
    • 流水线2: 3 -> 10 (总耗时: 3 + 10 = 13)
    • 流水线3: 4 (总耗时: 4)
  • 最大总耗时为 13,因此输出 13。
    在这里插入图片描述

通过上述步骤,我们可以高效地计算处理完所有作业的总时长。这种方法的时间复杂度主要由排序操作决定,为 O(n log n),其中 n 是作业数。

二、JavaScript算法源码

以下是 JavaScript 代码 的详细中文注释和讲解:


JavaScript 代码

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline"); // 引入 readline 模块,用于读取控制台输入// 创建 readline 接口实例
const rl = readline.createInterface({input: process.stdin,  // 输入流为标准输入output: process.stdout, // 输出流为标准输出
});const lines = []; // 定义一个数组 lines,用于存储输入的行数据// 监听 'line' 事件,每次读取一行输入
rl.on("line", (line) => {lines.push(line); // 将当前行数据存入 lines 数组// 当 lines 数组中有 2 行数据时,开始处理输入if (lines.length === 2) {// 解析第一行输入let [m, n] = lines[0].split(" ").map((ele) => parseInt(ele)); // 将第一行按空格分割,并转换为整数// 解析第二行输入let times = lines[1].split(" ") // 将第二行按空格分割.slice(0, n) // 只取前 n 个元素.map((ele) => parseInt(ele)); // 将每个元素转换为整数times.sort((a, b) => a - b); // 对 times 数组进行升序排序let mArr = new Array(m).fill(0); // 创建一个长度为 m 的数组 mArr,初始值为 0// 遍历 times 数组,将每个任务分配给当前负载最小的机器times.forEach((time, idx) => {mArr[idx % m] += time; // 将任务分配给 idx % m 号机器});console.log(Math.max(...mArr)); // 输出 mArr 数组中的最大值,即所有机器中最大的负载lines.length = 0; // 清空 lines 数组,为下一次输入做准备}
});

代码讲解

1. 输入部分
  • readline 模块
    • 使用 readline 模块读取控制台输入。
    • 通过 rl.on("line", ...) 监听每一行输入。
  • lines 数组
    • 用于存储输入的行数据。
    • lines 数组中有 2 行数据时,开始处理输入。
2. 数据处理部分
  • 解析第一行输入
    • 使用 split(" ") 将第一行按空格分割。
    • 使用 map((ele) => parseInt(ele)) 将分割后的字符串转换为整数。
    • 提取 m(机器数量)和 n(任务数量)。
  • 解析第二行输入
    • 使用 split(" ") 将第二行按空格分割。
    • 使用 slice(0, n) 只取前 n 个元素。
    • 使用 map((ele) => parseInt(ele)) 将分割后的字符串转换为整数。
  • 排序
    • times 数组进行升序排序,确保任务按时间从小到大分配。
3. 任务分配部分
  • mArr 数组
    • 创建一个长度为 m 的数组 mArr,初始值为 0。
    • 用于记录每台机器的总负载。
  • 任务分配逻辑
    • 遍历 times 数组,将每个任务分配给当前负载最小的机器。
    • 使用 idx % m 实现轮询分配。
4. 输出部分
  • Math.max(...mArr)
    • 计算 mArr 数组中的最大值,即所有机器中最大的负载。
    • 使用 console.log 输出结果。
5. 清空 lines 数组
  • 在处理完当前输入后,清空 lines 数组,为下一次输入做准备。

示例运行

输入 1
3 5
1 2 3 4 5
  • 输出
    7
    
  • 解释
    • m = 3(3 台机器),n = 5(5 个任务)。
    • 任务时间数组为 [1, 2, 3, 4, 5]
    • 分配结果:
      • 机器 0:1 + 4 = 5
      • 机器 1:2 + 5 = 7
      • 机器 2:3 = 3
    • 最大负载为 7
输入 2
2 4
3 1 7 2
  • 输出
    8
    
  • 解释
    • m = 2(2 台机器),n = 4(4 个任务)。
    • 任务时间数组为 [1, 2, 3, 7](排序后)。
    • 分配结果:
      • 机器 0:1 + 7 = 8
      • 机器 1:2 + 3 = 5
    • 最大负载为 8

总结

  • 该代码通过轮询分配的方式,将任务分配给负载最小的机器。
  • 使用 readline 模块读取控制台输入,并动态处理输入数据。
  • 如果有其他问题,欢迎继续提问!

三、Java算法源码

以下是 Java 代码 的详细中文注释和讲解:


Java 代码

import java.util.Arrays; // 导入 Arrays 工具类,用于数组排序和流操作
import java.util.Scanner; // 导入 Scanner 类,用于读取控制台输入public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in); // 创建 Scanner 对象,用于读取输入int m = sc.nextInt(); // 读取机器数量 mint n = sc.nextInt(); // 读取任务数量 nint[] times = new int[n]; // 定义数组 times,用于存储每个任务的执行时间for (int i = 0; i < n; i++) times[i] = sc.nextInt(); // 读取每个任务的执行时间并存入 times 数组System.out.println(getResult(m, n, times)); // 调用 getResult 方法计算结果并输出}/*** 计算所有机器中最大的负载* @param m 机器数量* @param n 任务数量* @param times 每个任务的执行时间数组* @return 所有机器中最大的负载*/public static int getResult(int m, int n, int[] times) {Arrays.sort(times); // 对任务执行时间数组进行升序排序int[] mArr = new int[m]; // 定义数组 mArr,用于记录每台机器的总负载for (int i = 0; i < n; i++) {mArr[i % m] += times[i]; // 将任务分配给当前负载最小的机器(轮询分配)}return Arrays.stream(mArr).max().orElse(0); // 返回 mArr 数组中的最大值(最大负载)}
}

代码讲解

1. 输入部分
  • Scanner
    • 使用 Scanner 类读取控制台输入。
    • 通过 sc.nextInt() 依次读取机器数量 m、任务数量 n 以及每个任务的执行时间。
  • times 数组
    • 用于存储每个任务的执行时间。
    • 通过循环读取输入并存入 times 数组。
2. 数据处理部分
  • 排序
    • 使用 Arrays.sort(times)times 数组进行升序排序,确保任务按执行时间从小到大分配。
  • 任务分配
    • 定义数组 mArr,用于记录每台机器的总负载。
    • 使用循环将任务分配给当前负载最小的机器(通过 i % m 实现轮询分配)。
3. 输出部分
  • Arrays.stream(mArr).max().orElse(0)
    • 使用流操作计算 mArr 数组中的最大值(即所有机器中最大的负载)。
    • 如果数组为空,则返回默认值 0
  • System.out.println
    • 输出计算结果。

示例运行

输入 1
3 5
1 2 3 4 5
  • 输出
    7
    
  • 解释
    • m = 3(3 台机器),n = 5(5 个任务)。
    • 任务时间数组为 [1, 2, 3, 4, 5]
    • 分配结果:
      • 机器 0:1 + 4 = 5
      • 机器 1:2 + 5 = 7
      • 机器 2:3 = 3
    • 最大负载为 7
输入 2
2 4
3 1 7 2
  • 输出
    8
    
  • 解释
    • m = 2(2 台机器),n = 4(4 个任务)。
    • 任务时间数组为 [1, 2, 3, 7](排序后)。
    • 分配结果:
      • 机器 0:1 + 7 = 8
      • 机器 1:2 + 3 = 5
    • 最大负载为 8

总结

  • 该代码通过轮询分配的方式,将任务分配给负载最小的机器。
  • 使用 Arrays.sort 对任务执行时间进行排序,确保任务按时间从小到大分配。
  • 使用流操作计算数组中的最大值,简化代码逻辑。
  • 如果有其他问题,欢迎继续提问!

四、Python算法源码

以下是 Python 代码 的详细中文注释和讲解:


Python 代码

# 输入获取
m, n = map(int, input().split())  # 读取机器数量 m 和任务数量 n
times = list(map(int, input().split()))  # 读取每个任务的执行时间并存入列表 times# 算法入口
def getResult():times.sort()  # 对任务执行时间列表进行升序排序mArr = [0] * m  # 定义列表 mArr,用于记录每台机器的总负载,初始值为 0for i in range(len(times)):  # 遍历任务执行时间列表mArr[i % m] += times[i]  # 将任务分配给当前负载最小的机器(轮询分配)return max(mArr)  # 返回 mArr 列表中的最大值(最大负载)# 算法调用
print(getResult())  # 调用 getResult 方法计算结果并输出

代码讲解

1. 输入部分
  • input().split()
    • 使用 input().split() 读取一行输入,并按空格分割成多个字符串。
  • map(int, ...)
    • 将分割后的字符串转换为整数。
  • m, n
    • 分别表示机器数量 m 和任务数量 n
  • times 列表
    • 用于存储每个任务的执行时间。
2. 数据处理部分
  • 排序
    • 使用 times.sort()times 列表进行升序排序,确保任务按执行时间从小到大分配。
  • 任务分配
    • 定义列表 mArr,用于记录每台机器的总负载,初始值为 0
    • 使用循环将任务分配给当前负载最小的机器(通过 i % m 实现轮询分配)。
3. 输出部分
  • max(mArr)
    • 计算 mArr 列表中的最大值(即所有机器中最大的负载)。
  • print(getResult())
    • 调用 getResult 方法计算结果并输出。

示例运行

输入 1
3 5
1 2 3 4 5
  • 输出
    7
    
  • 解释
    • m = 3(3 台机器),n = 5(5 个任务)。
    • 任务时间列表为 [1, 2, 3, 4, 5]
    • 分配结果:
      • 机器 0:1 + 4 = 5
      • 机器 1:2 + 5 = 7
      • 机器 2:3 = 3
    • 最大负载为 7
输入 2
2 4
3 1 7 2
  • 输出
    8
    
  • 解释
    • m = 2(2 台机器),n = 4(4 个任务)。
    • 任务时间列表为 [1, 2, 3, 7](排序后)。
    • 分配结果:
      • 机器 0:1 + 7 = 8
      • 机器 1:2 + 3 = 5
    • 最大负载为 8

总结

  • 该代码通过轮询分配的方式,将任务分配给负载最小的机器。
  • 使用 sort() 对任务执行时间进行排序,确保任务按时间从小到大分配。
  • 使用 max() 计算列表中的最大值,简化代码逻辑。
  • 如果有其他问题,欢迎继续提问!

五、C/C++算法源码:

以下是 C 语言代码C++ 代码 的详细中文注释和讲解:


C 语言代码

#include <stdio.h>
#include <stdlib.h>#define MAX(a, b) ((a) > (b) ? (a) : (b)) // 定义宏 MAX,用于比较两个数的大小// 比较函数,用于 qsort 排序
int cmp(const void* a, const void* b) {return (*(int*)a) - (*(int*)b); // 升序排序
}int main() {int m, n;scanf("%d %d", &m, &n); // 读取机器数量 m 和任务数量 nint times[n]; // 定义数组 times,用于存储每个任务的执行时间for (int i = 0; i < n; i++) {scanf("%d", &times[i]); // 读取每个任务的执行时间并存入 times 数组}qsort(times, n, sizeof(int), cmp); // 对任务执行时间数组进行升序排序int* mArr = (int*)calloc(m, sizeof(int)); // 动态分配数组 mArr,用于记录每台机器的总负载,初始值为 0for (int i = 0; i < n; i++) {mArr[i % m] += times[i]; // 将任务分配给当前负载最小的机器(轮询分配)}int ans = mArr[0]; // 初始化最大负载为 mArr[0]for (int i = 1; i < m; i++) {ans = MAX(ans, mArr[i]); // 遍历 mArr,找到最大值}printf("%d\n", ans); // 输出最大负载free(mArr); // 释放动态分配的内存return 0;
}

C++ 代码

#include <iostream>
#include <vector>
#include <algorithm> // 包含 sort 函数using namespace std;int main() {int m, n;cin >> m >> n; // 读取机器数量 m 和任务数量 nvector<int> times(n); // 定义 vector times,用于存储每个任务的执行时间for (int i = 0; i < n; i++) {cin >> times[i]; // 读取每个任务的执行时间并存入 times 数组}sort(times.begin(), times.end()); // 对任务执行时间数组进行升序排序vector<int> mArr(m, 0); // 定义 vector mArr,用于记录每台机器的总负载,初始值为 0for (int i = 0; i < n; i++) {mArr[i % m] += times[i]; // 将任务分配给当前负载最小的机器(轮询分配)}int ans = *max_element(mArr.begin(), mArr.end()); // 使用 max_element 找到 mArr 中的最大值cout << ans << endl; // 输出最大负载return 0;
}

代码讲解

1. 输入部分
  • C 语言
    • 使用 scanf 读取机器数量 m 和任务数量 n
    • 使用循环读取每个任务的执行时间并存入 times 数组。
  • C++
    • 使用 cin 读取机器数量 m 和任务数量 n
    • 使用 vector 存储任务执行时间,并通过循环读取输入。
2. 数据处理部分
  • 排序
    • C 语言:使用 qsorttimes 数组进行升序排序。
    • C++:使用 sorttimes 数组进行升序排序。
  • 任务分配
    • C 语言:动态分配数组 mArr,用于记录每台机器的总负载,并通过循环将任务分配给当前负载最小的机器。
    • C++:使用 vector 存储每台机器的总负载,并通过循环将任务分配给当前负载最小的机器。
3. 输出部分
  • C 语言
    • 使用循环遍历 mArr,找到最大值并输出。
    • 使用 free 释放动态分配的内存。
  • C++
    • 使用 max_element 找到 mArr 中的最大值并输出。

示例运行

输入 1
3 5
1 2 3 4 5
  • 输出
    7
    
  • 解释
    • m = 3(3 台机器),n = 5(5 个任务)。
    • 任务时间数组为 [1, 2, 3, 4, 5]
    • 分配结果:
      • 机器 0:1 + 4 = 5
      • 机器 1:2 + 5 = 7
      • 机器 2:3 = 3
    • 最大负载为 7
输入 2
2 4
3 1 7 2
  • 输出
    8
    
  • 解释
    • m = 2(2 台机器),n = 4(4 个任务)。
    • 任务时间数组为 [1, 2, 3, 7](排序后)。
    • 分配结果:
      • 机器 0:1 + 7 = 8
      • 机器 1:2 + 3 = 5
    • 最大负载为 8

总结

  • C 语言
    • 使用 qsort 进行排序,动态分配内存,手动遍历数组找到最大值。
  • C++
    • 使用 vectorsort 简化代码,使用 max_element 找到最大值。
  • 如果有其他问题,欢迎继续提问!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/66292.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

opencv图像基础学习

2.3图像的加密解密 源码如下&#xff1a; import cv2 import numpy as np import matplotlib.pyplot as plt def passImg():imgcv2.imread(./image/cat.jpg,0)h,wimg.shape#生成一个密码&#xff0c;加密key_imgnp.random.randint(0,256,size(h,w),dtypenp.uint8)img_addmcv2…

【机器学习】零售行业的智慧升级:机器学习驱动的精准营销与库存管理

我的个人主页 我的领域&#xff1a;人工智能篇&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;&#x1f44d;点赞 收藏❤ 在当今数字化浪潮汹涌澎湃的时代&#xff0c;零售行业正站在转型升级的十字路口。市场竞争的白热化使得企业必须另辟蹊径&#xff0…

Navicat Premium 原生支持阿里云 PolarDB 数据库

近日&#xff0c;我司旗下的 Navicat Premium 软件通过了阿里云 PolarDB 数据库产品生态集成认证&#xff0c;这标志着 Navicat 通过原生技术全面实现了对秒级弹性、高性价比、稳定可靠的PolarDB 数据库三大引擎&#xff08;PolarDB MySQL版、PolarDB PostgreSQL版和 PolarDB f…

【SpringBoot应用篇】SpringBoot+MDC+自定义Filter操作traceId实现日志链路追踪

【SpringBoot应用篇】SpringBootMDC自定义Filter操作traceId实现日志链路追踪 解决的问题解决方案MDC具体逻辑ymllogback-spring.xmlTraceIdUtil操作工具类TraceIdFilter自定义过滤器GlobalExceptionHandler全局异常处理类TraceIdAspect切面UserController测试验证 多线程处理M…

python如何解析word文件格式(.docx)

python如何解析word文件格式&#xff08;.docx&#xff09; .docx文件遵从开源的“Office Open XML标准”&#xff0c;这意味着我们能用python的文本操作对它进行操作&#xff08;实际上PPT和Excel也是&#xff09;。而且这并不是重复造轮子&#xff0c;因为市面上操作.docx的…

python爬虫报错日记

python爬虫报错日记 类未定义 原因&#xff1a;代码检查没有问题**&#xff0c;位置错了**&#xff0c;测试代码包含在类里…… UnicodedecodeError错误 原因&#xff1a;字符没有自动转换成utf-8格式 KeyError&#xff1a;“href” 原因&#xff1a;前面运行正常&#x…

第34天:Web开发-PHP应用鉴别修复AI算法流量检测PHP.INI通用过滤内置函数

#知识点 1、安全开发-原生PHP-PHP.INI安全 2、安全开发-原生PHP-全局文件&单函数 3、安全开发-原生PHP-流量检测&AI算法 一、通用-PHP.INI设置 参考&#xff1a; https://www.yisu.com/ask/28100386.html https://blog.csdn.net/u014265398/article/details/109700309 …

基于PHP的校园新闻发布管理

摘要 近年来&#xff0c;随着互联网技术的迅速发展&#xff0c;人们获取新闻的渠道也变得越来越多样化&#xff0c;已经不再拘束于传统的报纸、期刊、杂志等纸质化的方式&#xff0c;而是通过网络满足了人们获得第一手新闻的愿望&#xff0c;这样更加有助于实现新闻的规范化管…

从玩具到工业控制--51单片机的跨界传奇【3】

在科技的浩瀚宇宙中&#xff0c;51 单片机就像一颗独特的星辰&#xff0c;散发着神秘而迷人的光芒。对于无数电子爱好者而言&#xff0c;点亮 51 单片机上的第一颗 LED 灯&#xff0c;不仅仅是一次简单的操作&#xff0c;更像是开启了一扇通往新世界的大门。这小小的 LED 灯&am…

boss直聘 __zp_stoken__ 逆向分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我删…

【日志篇】(7.6) ❀ 01. 在macOS下刷新FortiAnalyzer固件 ❀ FortiAnalyzer 日志分析

【简介】FortiAnalyzer 是 Fortinet Security Fabric 安全架构的基础&#xff0c;提供集中日志记录和分析&#xff0c;以及端到端可见性。因此&#xff0c;分析师可以更有效地管理安全状态&#xff0c;将安全流程自动化&#xff0c;并快速响应威胁。具有分析和自动化功能的集成…

Linux 内核自旋锁spinlock(一)

文章目录 前言一、自旋锁1.1 简介1.2 API1.2.1 spin_lock/spin_unlock1.2.2 spin_lock_irq/spin_unlock_irq1.2.3 spin_lock_irqsave/spin_unlock_irqstore1.2.4 spin_lock_bh/spin_unlock_bh1.2.5 补充 二、自选锁原理三、自旋锁在内核的使用3.1 struct file3.2 struct dentry…

【太古新篇,智驭未来】 SFA系统成功上线

经过双方团队的不懈努力与紧密合作&#xff0c;eBest成功帮助香港太古可乐完成了SFA系统的全面上线&#xff01; 太古可乐&#xff0c;作为饮料行业的佼佼者&#xff0c;一直以来以其卓越的品质和深入人心的品牌形象深受消费者喜爱。然而&#xff0c;在快速变化的市场环境中&am…

Web安全|渗透测试|网络安全

基础入门(P1-P5) p1概念名词 1.1域名 什么是域名&#xff1f; 域名&#xff1a;是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称&#xff0c;用于在数据传输时对计算机的定位标识&#xff08;有时也指地理位置&#xff09;。 什么是二级域名多级域名…

陈萍的设计创新:Kevlin Nexus荣获伦敦设计奖,展示品牌设计的国际化与持续创新

近日,陈萍凭借其创新设计作品 Kevlin Nexus,成功斩获 2024 伦敦设计奖。该奖项旨在表彰全球范围内的优秀设计作品,表彰设计界最完美、最前沿的成就。伦敦设计奖是全球最具权威性和影响力的设计奖项之一,其评选标准以高水准的专业性和严格性著称。作为全球设计界的顶级荣誉,伦敦…

qml DirectionalBlur详解

1、概述 DirectionalBlur是QML&#xff08;Qt Modeling Language&#xff09;中用于创建方向模糊效果的一种图形效果类型。它通过对源图像的像素进行模糊处理&#xff0c;产生一种源项目朝着模糊方向移动的感知印象。这种模糊效果被应用到每个像素的两侧&#xff0c;因此设置方…

怎么投稿各大媒体网站?如何快速辨别一家媒体是否适合自己?

在做软文营销时&#xff0c;除去在官号和子账号上投稿外&#xff0c;怎么投稿各大媒体网站是困扰中小企业主的一大难题。没有多余账号、运营成本太高&#xff0c;让不少想做全平台推广的朋友止步于此。为了解决这些问题&#xff0c;今天就让小编来分享一下&#xff0c;怎么在各…

MES设备日志采集工具

永久免费: <下载> <使用说明> 用途 定时全量或增量采集工控机,电脑文件或日志. 优势 开箱即用: 解压直接运行.不需额外下载.管理设备: 后台统一管理客户端.无人值守: 客户端自启动,自更新.稳定安全: 架构简单,兼容性好,通过授权控制访问. 架构 技术架构: Asp…

Formality:参考设计/实现设计以及顶层设计

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482​​​ Formality存在两个重要的概念&#xff1a;参考设计/实现设计和顶层设计&#xff0c;本文就将对此进行详细阐述。参考设计/实现设计是中两个重要的全局概念&am…

国产编辑器EverEdit - 复制为RTF

1 复制为RTF 1.1 应用背景 在写产品手册或者其他文档时&#xff0c;可能会用到要将产品代码以样例的形式放到文档中&#xff0c;一般的文本编辑器拷贝粘贴到Word中也就是普通文本&#xff0c;没有语法着色&#xff0c;这样感观上不是太好&#xff0c;为了让读者的感观更好一点…