22.04.29机试记录

本文探讨了如何通过模拟和排序策略优化模型训练和运行时间,以求解多模型调度问题。第一题展示了利用longlong类型避免训练时间溢出的方法,第二题涉及连续数组操作与重复数字检测,第三题涉及删除情节构造回文,第四题关注树木移植以最大化高度占比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一题

  小多有若干个机器学习模型,每个模型都需要先经过训练再经过运行验证才能完成。小多只有一台训练机,每次只能训练一个模型,每个模型训练完成后可以立即运行,但多个模型可以同时运行。请你求出小多完成所有模型的最短时间。
第一行输入模型的个数,从第二行开始,第一个数是模型运行的时间,第二个数是模型训练的时间,输出所有模型完成的最短时间。模型个数,训练时间,运行时间均处于[1, 100000]内。
示例1
输入:

3
4 1
2 5
3 100

输出:

108
//按照132的顺序训练,第1个模型完成的时间为5,第3个模型完成的时间为104,第2个模型完成的时间为108

解答:
  本题使用模拟做法,所有的模型都要逐个经过训练,因此总训练时间是不变的,所以要尽可能减少运行时间,由于运行可以同时进行,所以需要将模型按照运行时间从大到小排序,逐个计算当前模型的完成时间,取最小值。这题AC一直卡在60%,后来发现是trainTime溢出了,换成long long就好了。
代码:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 为了看中间变量而设计的函数,不需要
// void printPair(vector<pair<int, int>> &nums);
// 自定义排序,从大到小排
bool mySort(pair<int, int> a, pair<int, int> b)
{
    return a.first > b.first;
}
// 输出最小运行时间
void getTime(vector<pair<int, int>> &experiment, int n)
{
    sort(experiment.begin(), experiment.end(), mySort); // 将输入按运行时间从大到小排序
    long long trainTime = 0, maxTime = 0;
    for (auto ite = experiment.begin(); ite != experiment.end(); ite++)
    {
        trainTime += ite->second; // 计算每个模型的训练开始时间
        maxTime = max(maxTime, trainTime + ite->first); // 取最大的运行结束时间
    }
//     printPair(experiment);
    cout << maxTime << endl;
}

// void printPair(vector<pair<int, int>> &nums) {
//     for (auto ite = nums.begin(); ite != nums.end(); ite++) {
//         cout << ite->first << ite->second << endl;
//     }
// }

int main()
{
    int n;
    cin >> n;
    vector<pair<int, int>> experiment; // 使用pair数组储存输入的数据
    for (int i = 0; i < n; i++)
    {
        int a, b;
        cin >> a >> b;
        experiment.push_back(make_pair(a, b));
    }
    getTime(experiment, n);
    system("pause");
    return 0;
}

第二题

  输入一个整数数组,第一步取相邻两个数的绝对值,得到一个新的数组。如果这个新的数组中的数字都是连续的,就输出YES、最大值和最小值;否则就输出NO、数字的最大重复次数和缺少的数字个数。
示例1
输入:

4
4 1 3 2

输出:

YES
1 3

示例2
输入:

4
4 3 2 1

输出:

NO
3 0

解答:
  这道题其实也可以使用模拟解法:

  1. 将输入的数字两两取绝对值,再排序,获得新的数组;
  2. 使用unordered_map统计每个数字出现的次数;
  3. 遍历unordered_map,获得最大重复次数和所有重复的次数;
  4. 判断条件为“最大重复次数=1 && 所有重复次数 = 0 && 最大最小值的差 = 数组长度”
  5. 如果输出NO,求缺少的数字个数是关键,缺少的数字个数 = 最大值 - 最小值 + 1 - 数组长度 + 所有重复次数

代码:

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

vector<int> getNums(vector<int> &nums, int n) {
	vector<int> res;
	for (int i = 0; i < n - 1; i++) {
		res.push_back(nums[i + 1] - nums[i]); // 获得新的数组
	}
	sort(res.begin(), res.end()); // 数组排序,方便后面计算
	return res;
}

void isValid(vector<int> &nums, int n) {
	unordered_map<int, int> mp;
	for (int num : nums) {
		mp[num]++; // 统计数字出现的次数
	}
	int maxCount = 0; // 最大出现次数
	int count = 0; // 总重复次数
	for (auto ite = mp.begin(); ite != mp.end(); ite++) {
		if (ite->second > 1) {
			maxCount = max(maxCount, ite->second); // 更新最大出现次数
			count += ite->second - 1; // 更新总重复次数
		}
	}
	if (maxCount == 1 && count == 0 && nums[n - 1] - nums[0] + 1 == n) {
		cout << "YES" << endl;
		cout << nums[0] << " " << nums[n - 1] << endl;
	}
	else {
		cout << "NO" << endl;
		cout << maxCount << " " << nums[n - 1] - nums[0] + 1 - n + count << endl;
	}
}

int main() {
	int n;
	cin >> n;
	vector<int> nums;
	for (int i = 0; i < n; i++) {
		int num;
		cin >> num;
		nums.push_back(num);
	}
	vector<int> tmp = getNums(nums, n);
	isValid(tmp, n - 1);
	return 0;
}

第三题

  把小说看做由N个情节组成,每个情节可用非空字符串 S i S_i Si表示, S i S_i Si的长度不大于3,可以删除任意情节(0个或多个),不可以打乱字符串顺序,使得剩余情节按顺序构成回文。
示例1
输入:

4
ab
a
abc
ba

输出:

YES // 删除a和abc后,剩余字符串为abba,构成回文

第四题

  现有一个林场,要把部分树移植到别处,使得移植之后,高度最高的树占所有树的一半以上。每棵树有高度和移植时间两个属性,求最短的移植时间。
  输入的第一行是林场数目的数目,第二行开始,第一个数字是树的高度,第二个数字是移植时间。
示例1

2
1 3
2 2

输出

2 //最高树高度为2,有1棵,未超过总数的一半,所以移植走高度为2的树,剩余最高的树高度为1,耗时为3

示例2
输入

3
1 1
2 2
2 2

输出

0 //最高的树高度为2,有两棵,超过总数一半,无需移植

示例3
输入

6
1 5
1 5
2 4
2 3
3 1
3 2

输出

8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值