华为OD机试真题 - 最优策略组合下的总的系统消耗资源数 - 2024E卷(Java、Python、JavaScript、C、C++合集)

本文介绍了一种通信系统中用户调度的问题,给定N个用户和三种调度策略,需保证相邻用户策略不同,每个用户选择消耗最少的策略。通过示例和多种编程语言的实现展示了如何计算最优策略组合下系统的总资源消耗。

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

一、题目描述

在通信系统中有一个常见的问题是对用户进行不同策略的调度,会得到不同系统消耗的性能。

假设由N个待串行用户,每个用户可以使用A/B/C三种不同的调度策略,不同的策略会消耗不同的系统资源。

请你根据如下规则进行用户调度,并返回总的消耗资源数。

规则是:相邻的用户不能使用相同的调度策略。

例如:

  1. 第一个用户使用A策略 则第二个用户只能使用B和C策略;
  2. 对单的用户而言,不同的调度策略对系统资源的消耗可以规划后抽象为数值;

例如:

  1. 某用户分别使用ABC策略的系统消耗,分别为15 8 17;
  2. 每个用户依次选择当前所能选择的对系统资源消耗最少的策略,局部最优;
  3. 如果有多个满足要求的策略,选最后一个。

二、输入描述

第一行表示用户个数N。
接下来表示每一行表示一个用户分别使用三个策略的资源消耗,resA resB resC。

三、输出描述

最优策略组合下的总的系统消耗资源数。

四、解题思路

  1. 读取输入的用户数量 n;
  2. 创建一个列表 lists,用于存储每个用户的不同策略和资源消耗;
  3. 循环读取每个用户的资源消耗,将其添加到 lists 中;
  4. 初始化变量 total 表示总的系统消耗资源数,变量 preUser 表示上一个用户所选的策略;
  5. 对每个用户进行调度:
    • 对当前用户的所有策略按照资源消耗从低到高排序,如果资源消耗相同,则将策略索引较大的排在前面,以满足选择最后一个的要求;
    • 遍历排序后的策略,如果是第一个用户,或者当前策略与上一个用户所选的策略不同,选择该策略,并将其资源消耗加到 total 中,更新 preUser 为当前策略索引,然后跳出循环。
  6. 输出 total,即最优策略组合下的总的系统消耗资源数。

五、Java算法源码

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int n = scanner.nextInt();

    List<List<User>> lists = new ArrayList<List<User>>(n);
    for (int i = 0; i < n; i++) {
        List<User> iUserList = new ArrayList<>(3);
        for (int j = 0; j < 3; j++) {
            User User = new User();
            User.index = j;
            User.value = scanner.nextInt();
            iUserList.add(User);
        }
        lists.add(iUserList);
    }

    int total = 0;
    int preUser = -1;
    for (int i = 0; i < n; i++) {
        // 当前用户的所有策略,按照资源消耗从低到高排序,消耗一样多的,index大的排在前面
        List<User> iUserList = lists.get(i);
        iUserList = iUserList.stream()
                .sorted(Comparator.comparing(User::getIndex)) // 如果有多个满足要求的策略,选最后一个,所以排在前面供选择
                .sorted(Comparator.comparing(User::getValue)) // 后执行的优先级高
                .collect(Collectors.toList());
        for (User User : iUserList) {
            // 第一个用户,或者后面的用户和之前用户不是同一个
            if (preUser == -1 || User.getIndex() != preUser) {
                total += User.getValue();
                preUser = User.getIndex();
                break;
            }
        }
    }
    System.out.println(total);
}

private static class User {
    public int index;
    public int value;

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

六、效果展示

1、输入

3
15 8 17
12 20 9
11 7 5

2、输出

24

3、说明

1号用户使用B策略
2号用户使用C策略
3号用户使用B策略
系统资源消耗8+9+7。

4、思路

  1. 每个用户可以使用A/B/C三种不同的调度策略,即固定3种;
  2. 每个用户依次选择当前所能选择的对系统资源消耗最少的策略,局部最优,每个用户的策略需要根据资源消耗进行排序;
  3. 相邻的用户不能使用相同的调度策略,即上一个用户选择的这个策略,当前用户就不能再选择;
  4. 如果有多个满足要求的策略,选最后一个。所以还要考虑不同策略消耗资源相等的情况;
  5. 遍历处理每个用户可选择的消耗最小的策略相加;
  6. 可以考虑面向对象编程,代码更易懂;

七、JavaScript算法源码

// 创建一个用于读取用户输入的函数  
function readInput() {  
    return parseInt(prompt("请输入一个整数n:"));  
}  
  
// 定义一个User类  
class User {  
    constructor(index, value) {  
        this.index = index;  
        this.value = value;  
    }  
  
    getIndex() {  
        return this.index;  
    }  
  
    getValue() {  
        return this.value;  
    }  
}  
  
// 主函数  
function main() {  
    // 读取用户输入的整数n  
    const n = readInput();  
  
    // 创建一个二维数组来存储User对象  
    const lists = new Array(n).fill(null).map(() => []);  
  
    // 读取n个用户的3个策略信息  
    for (let i = 0; i < n; i++) {  
        // 读取当前用户的3个策略信息  
        for (let j = 0; j < 3; j++) {  
            const value = parseInt(prompt(`请输入第${i + 1}个用户的第${j + 1}个策略的值:`));  
            // 创建一个User对象并添加到当前用户的策略列表中  
            lists[i].push(new User(j, value));  
        }  
    }  
  
    // 初始化总值为0  
    let total = 0;  
    // 初始化前一个用户的index为-1  
    let preUser = -1;  
  
    // 遍历每个用户的策略列表  
    for (let i = 0; i < n; i++) {  
        // 获取当前用户的策略列表  
        const iUserList = lists[i];  
  
        // 按照资源消耗从低到高排序,如果消耗一样多,index大的排在前面  
        iUserList.sort((a, b) => {  
            if (a.index === b.index) {  
                return a.value - b.value;  
            }  
            return a.index - b.index;  
        });  
  
        // 遍历当前用户的策略  
        for (const user of iUserList) {  
            // 如果是第一个用户,或者当前用户和前一个用户不是同一个  
            if (preUser === -1 || user.getIndex() !== preUser) {  
                total += user.getValue();  
                preUser = user.getIndex();  
                break; // 找到满足条件的策略后跳出循环  
            }  
        }  
    }  
  
    // 输出总值  
    console.log(total);  
}  
  
// 调用主函数  
main();

八、Python算法源码

# 导入需要的库  
from typing import List  
  
# 定义User类  
class User:  
    def __init__(self, index: int, value: int):  
        self.index = index  
        self.value = value  
  
    def get_index(self) -> int:  
        return self.index  
  
    def get_value(self) -> int:  
        return self.value  
  
# 主函数  
def main():  
    # 从用户输入读取整数n  
    n = int(input("请输入一个整数n: "))  
  
    # 创建一个列表来存储用户列表  
    lists = [[] for _ in range(n)]  
    for i in range(n):  
        # 创建当前用户的策略列表  
        user_list = []  
        for j in range(3):  
            # 创建User对象并添加到当前用户的策略列表中  
            user = User(j, int(input(f"请输入第{i+1}个用户的第{j+1}个策略的值: ")))  
            user_list.append(user)  
        # 将当前用户的策略列表添加到总列表中  
        lists.append(user_list)  
  
    # 初始化总值为0  
    total = 0  
    # 初始化前一个用户的index为-1  
    pre_user = -1  
  
    # 遍历每个用户的策略列表  
    for i in range(n):  
        # 获取当前用户的策略列表  
        i_user_list = lists[i]  
  
        # 对当前用户的策略列表按照index升序和value升序排序  
        # 注意:Python中列表的sort方法默认是稳定的,即相同元素的相对顺序不会改变  
        i_user_list.sort(key=lambda u: (u.get_index(), u.get_value()))  
  
        # 遍历当前用户的策略  
        for user in i_user_list:  
            # 如果是第一个用户,或者当前用户和前一个用户不是同一个  
            if pre_user == -1 or user.get_index() != pre_user:  
                total += user.get_value()  
                pre_user = user.get_index()  
                break  # 找到满足条件的策略后跳出循环  
  
    # 输出总值  
    print(total)  
  
# 调用主函数  
if __name__ == "__main__":  
    main()

九、C算法源码

#include <stdio.h>  
#include <stdlib.h>  
  
// 定义User结构体  
typedef struct User {  
    int index;  
    int value;  
} User;  
  
// 比较函数,用于qsort排序  
int compareUsers(const void *a, const void *b) {  
    User *userA = (User *)a;  
    User *userB = (User *)b;  
      
    // 先按index升序排序  
    if (userA->index != userB->index) {  
        return userA->index - userB->index;  
    }  
    // 如果index相同,按value升序排序  
    return userA->value - userB->value;  
}  
  
int main(int argc, char *argv[]) {  
    int n;  
    printf("请输入用户数量n: ");  
    scanf("%d", &n);  
  
    // 分配二维数组空间,用于存储用户列表  
    User **lists = (User **)malloc(n * sizeof(User *));  
    for (int i = 0; i < n; i++) {  
        lists[i] = (User *)malloc(3 * sizeof(User));  
        for (int j = 0; j < 3; j++) {  
            printf("请输入第%d个用户的第%d个策略的值: ", i + 1, j + 1);  
            scanf("%d", &lists[i][j].value);  
            lists[i][j].index = j;  
        }  
    }  
  
    int total = 0;  
    int preUser = -1;  
    for (int i = 0; i < n; i++) {  
        // 对当前用户的策略列表进行排序  
        qsort(lists[i], 3, sizeof(User), compareUsers);  
  
        // 遍历当前用户的策略  
        for (int j = 0; j < 3; j++) {  
            // 第一个用户,或者后面的用户和之前用户不是同一个  
            if (preUser == -1 || lists[i][j].index != preUser) {  
                total += lists[i][j].value;  
                preUser = lists[i][j].index;  
                break; // 找到满足条件的策略后跳出循环  
            }  
        }  
    }  
  
    printf("总值: %d\n", total);  
  
    // 释放分配的内存  
    for (int i = 0; i < n; i++) {  
        free(lists[i]);  
    }  
    free(lists);  
  
    return 0;  
}

十、C++算法源码

#include <iostream>  
#include <vector>  
#include <algorithm>  
  
// 定义一个User结构体  
struct User {  
    int index;  
    int value;  
  
    // 获取index的方法  
    int getIndex() const {  
        return index;  
    }  
  
    // 获取value的方法  
    int getValue() const {  
        return value;  
    }  
};  
  
// 比较函数,用于std::sort  
bool compareUser(const User& a, const User& b) {  
    // 首先比较index,如果index相同则比较value  
    if (a.index == b.index) {  
        return a.value < b.value;  
    }  
    return a.index < b.index;  
}  
  
int main() {  
    int n;  
    std::cin >> n; // 从标准输入读取n  
  
    // 使用vector<vector<User>>来存储用户的列表  
    std::vector<std::vector<User>> lists(n);  
    for (int i = 0; i < n; ++i) {  
        // 为每个用户创建一个包含3个User的vector  
        std::vector<User> iUserList(3);  
        for (int j = 0; j < 3; ++j) {  
            User user;  
            user.index = j;  
            std::cin >> user.value; // 从标准输入读取value  
            iUserList[j] = user;  
        }  
        lists[i] = iUserList;  
    }  
  
    int total = 0;  
    int preUser = -1;  
    for (int i = 0; i < n; ++i) {  
        // 获取当前用户的所有策略,并进行排序  
        std::vector<User>& iUserList = lists[i];  
        std::sort(iUserList.begin(), iUserList.end(), compareUser);  
  
        for (const User& user : iUserList) {  
            // 如果是第一个用户,或者当前用户和上一个用户不是同一个  
            if (preUser == -1 || user.getIndex() != preUser) {  
                total += user.getValue();  
                preUser = user.getIndex();  
                break; // 找到满足条件的策略后跳出循环  
            }  
        }  
    }  
  
    std::cout << total << std::endl; // 输出总值  
    return 0;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值