题解 | #云服务器资源优化#

云服务器资源优化

https://www.nowcoder.com/practice/28976c0198844c13ab4e2e7c04e3979e

REALHW79 云服务器资源优化

题目链接

云服务器资源优化

题目描述

您是一位顶尖的云计算工程师,负责为一个客户在数据中心部署一组高性能计算服务。您拥有一台物理服务器,但这台服务器的总功耗预算是有限的。

现在,您需要从一系列待选服务中,挑选出一个最优的组合进行部署,以在满足功耗限制的前提下,实现最大的计算价值。

现有 个待部署的计算服务,按 升序编号,服务器的总功耗预算为

对于每个服务 ,我们有两个关键指标:

  • 功耗(Power Consumption):
  • 计算价值(Computing Value):

您的任务是选择一个服务的组合,同时满足以下两个条件:

  1. 所有被选中服务的总功耗之和不得超过服务器的功耗预算 ,即
  2. 所有被选中服务的总计算价值之和 应达到最大。

输出描述:

输出您最终选择的服务组合的编号,编号按从小到大排序,并用空格隔开。

择优规则(注意优先级):

  1. 如果没有任何一个服务组合能满足功耗预算,则输出 -1
  2. 如果存在多个服务组合都能达到相同的最高总计算价值,则在这些组合中,选择总功耗最小的那个。
  3. 如果在满足前一个条件后仍有多个组合,则在这些组合中,选择包含服务数量最少的那个。
  4. 题目保证在上述所有规则的约束下,最终只会有一组唯一的最优解。

解题思路

这是一个典型的 0/1 背包问题 的变种。标准的背包问题只要求解出最大价值,而本题不仅需要记录达到最大价值所选择的物品,还需要在价值相同时应用额外的择优规则。因此,我们需要对动态规划的状态定义和转移逻辑进行扩展。

1. DP 状态定义

为了处理复杂的择优规则,DP 状态不能只存储一个价值数值。我们需要一个能包含所有择优所需信息的复合状态。可以定义一个结构体或类 State,包含三个字段:

  • value: 总计算价值
  • power: 总功耗
  • count: 服务的数量

我们使用一个二维 DP 表 dp[i][j],它存储一个 State 对象,表示在考虑前 i 个服务、且功耗预算恰好为 j 的情况下的最优状态。

2. 状态转移与比较

我们遍历每个服务 i (从 1 到 N) 和每个功耗点 j (从 0 到 C)。对于 dp[i][j],我们有两种选择:

  1. 不选择服务 i:此时的最优状态直接继承自只考虑前 i-1 个服务的情况,即 dp[i-1][j]
  2. 选择服务 i:这个选择仅在当前功耗预算 j 大于等于服务 i 的功耗 P_i 时才可行。新状态由 dp[i-1][j - P_i](即不选服务 i 时的最优状态)加上服务 ivalue, power, 和 count 得到。

在更新 dp[i][j] 时,我们需要比较 “不选择服务 i 的状态” 和 “选择服务 i 的状态”,并选出更优的一个。这个比较必须严格遵循题目的择优规则:

  1. value 大的更优。
  2. value 相等,则 power 小的更优。
  3. power 也相等,则 count 小的更优。

3. 回溯路径

当 DP 表格 dp[N][C] 填充完毕后,dp[N][j] (对于所有 ) 存储了使用全部 N 个服务在不同功耗下的最优解。我们需要:

  1. 找到全局最优解:遍历 dp[N][0]dp[N][C],使用上述的择优比较逻辑,找到全局最优的 State 和其对应的功耗 j
  2. 回溯:从 dp[N][j] 开始,反向推导选择了哪些服务。
    • 对于当前状态 dp[i][j],如果它与 dp[i-1][j] 不同,说明服务 i 在这一步被选中了。我们将服务 i 的编号记录下来,然后将预算 j 减去服务 i 的功耗 P_i,继续考察 dp[i-1][j-P_i]
    • 如果 dp[i][j]dp[i-1][j] 相同,说明服务 i 未被选中,我们直接继续考察 dp[i-1][j]
    • 重复此过程直到 i=0

4. 输出

最后,将记录的服务编号排序后输出。如果最终没有选择任何服务(例如所有服务功耗都超预算),则输出 -1

代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct Service {
    int id;
    int power;
    int value;
};

struct State {
    long long value = 0;
    int power = 0;
    int count = 0;

    // 比较函数,判断 newState 是否比当前 state 更优
    bool is_better_than(const State& other) const {
        if (value > other.value) return true;
        if (value == other.value) {
            if (power < other.power) return true;
            if (power == other.power) {
                if (count < other.count) return true;
            }
        }
        return false;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    int c;
    cin >> c;

    vector<Service> services(n);
    for (int i = 0; i < n; ++i) {
        services[i].id = i + 1;
        cin >> services[i].power >> services[i].value;
    }

    vector<vector<State>> dp(n + 1, vector<State>(c + 1));

    for (int i = 1; i <= n; ++i) {
        int p = services[i - 1].power;
        int v = services[i - 1].value;

        for (int j = 0; j <= c; ++j) {
            // 默认不选第i个服务
            dp[i][j] = dp[i - 1][j];

            // 尝试选择第i个服务
            if (j >= p) {
                State prev_state = dp[i - 1][j - p];
                State new_state;
                new_state.value = prev_state.value + v;
                new_state.power = prev_state.power + p;
                new_state.count = prev_state.count + 1;

                if (new_state.is_better_than(dp[i][j])) {
                    dp[i][j] = new_state;
                }
            }
        }
    }

    // 在所有可能的总功耗中找到最优解
    State best_state = dp[n][0];
    int final_power = 0;
    for (int j = 1; j <= c; ++j) {
        if (dp[n][j].is_better_than(best_state)) {
            best_state = dp[n][j];
            final_power = j;
        }
    }

    if (best_state.value == 0) {
        cout << -1 << endl;
        return 0;
    }

    // 回溯找到选择的服务
    vector<int> result_ids;
    int current_power = final_power;
    for (int i = n; i > 0 && current_power > 0; --i) {
        // 比较状态对象需要比较所有成员
        bool is_equal = (dp[i][current_power].value == dp[i - 1][current_power].value &&
                         dp[i][current_power].power == dp[i - 1][current_power].power &&
                         dp[i][current_power].count == dp[i - 1][current_power].count);

        if (!is_equal) {
            result_ids.push_back(services[i - 1].id);
            current_power -= services[i - 1].power;
        }
    }

    sort(result_ids.begin(), result_ids.end());

    for (size_t i = 0; i < result_ids.size(); ++i) {
        cout << result_ids[i] << (i == result_ids.size() - 1 ? "" : " ");
    }
    cout << endl;

    return 0;
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

class Service {
    int id;
    int power;
    int value;

    public Service(int id, int power, int value) {
        this.id = id;
        this.power = power;
        this.value = value;
    }
}

class State {
    long value = 0;
    int power = 0;
    int count = 0;

    // 复制构造函数
    public State(State other) {
        this.value = other.value;
        this.power = other.power;
        this.count = other.count;
    }
    
    public State() {}

    // 判断 this 是否比 other 更优
    public boolean isBetterThan(State other) {
        if (this.value > other.value) return true;
        if (this.value == other.value) {
            if (this.power < other.power) return true;
            if (this.power == other.power) {
                if (this.count < other.count) return true;
            }
        }
        return false;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        State state = (State) obj;
        return value == state.value && power == state.power && count == state.count;
    }
}

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

        Service[] services = new Service[n];
        for (int i = 0; i < n; i++) {
            services[i] = new Service(i + 1, sc.nextInt(), sc.nextInt());
        }

        State[][] dp = new State[n + 1][c + 1];
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= c; j++) {
                dp[i][j] = new State();
            }
        }

        for (int i = 1; i <= n; i++) {
            int p = services[i - 1].power;
            int v = services[i - 1].value;

            for (int j = 0; j <= c; j++) {
                // 不选第i个服务
                dp[i][j] = new State(dp[i - 1][j]);

                // 尝试选第i个服务
                if (j >= p) {
                    State prevState = dp[i - 1][j - p];
                    State newState = new State();
                    newState.value = prevState.value + v;
                    newState.power = prevState.power + p;
                    newState.count = prevState.count + 1;

                    if (newState.isBetterThan(dp[i][j])) {
                        dp[i][j] = newState;
                    }
                }
            }
        }

        State bestState = dp[n][0];
        int finalPower = 0;
        for (int j = 1; j <= c; j++) {
            if (dp[n][j].isBetterThan(bestState)) {
                bestState = dp[n][j];
                finalPower = j;
            }
        }

        if (bestState.value == 0) {
            System.out.println(-1);
            return;
        }

        List<Integer> resultIds = new ArrayList<>();
        int currentPower = finalPower;
        for (int i = n; i > 0 && currentPower > 0; i--) {
            if (!dp[i][currentPower].equals(dp[i - 1][currentPower])) {
                resultIds.add(services[i - 1].id);
                currentPower -= services[i - 1].power;
            }
        }

        Collections.sort(resultIds);

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < resultIds.size(); i++) {
            sb.append(resultIds.get(i));
            if (i < resultIds.size() - 1) {
                sb.append(" ");
            }
        }
        System.out.println(sb.toString());
    }
}
import sys

class State:
    def __init__(self, value=0, power=0, count=0):
        self.value = value
        self.power = power
        self.count = count

def is_better(s1, s2):
    """判断 s1 是否比 s2 更优"""
    if s1.value > s2.value:
        return True
    if s1.value == s2.value:
        if s1.power < s2.power:
            return True
        if s1.power == s2.power:
            if s1.count < s2.count:
                return True
    return False

def is_equal(s1, s2):
    return s1.value == s2.value and s1.power == s2.power and s1.count == s2.count

def solve():
    lines = sys.stdin.readlines()
    if not lines:
        return

    n = int(lines[0])
    c = int(lines[1])
    services = []
    for i in range(n):
        p, v = map(int, lines[2 + i].split())
        services.append({'id': i + 1, 'power': p, 'value': v})

    dp = [[State() for _ in range(c + 1)] for _ in range(n + 1)]

    for i in range(1, n + 1):
        service = services[i - 1]
        p, v = service['power'], service['value']
        
        for j in range(c + 1):
            # 不选
            dp[i][j] = dp[i-1][j]
            
            # 选
            if j >= p:
                prev_state = dp[i-1][j-p]
                new_state = State(
                    value=prev_state.value + v,
                    power=prev_state.power + p,
                    count=prev_state.count + 1
                )
                if is_better(new_state, dp[i][j]):
                    dp[i][j] = new_state

    best_state = State()
    final_power = 0
    for j in range(c + 1):
        if is_better(dp[n][j], best_state):
            best_state = dp[n][j]
            final_power = j
            
    if best_state.value == 0:
        print(-1)
        return

    result_ids = []
    current_power = final_power
    for i in range(n, 0, -1):
        if not is_equal(dp[i][current_power], dp[i-1][current_power]):
            service = services[i - 1]
            result_ids.append(service['id'])
            current_power -= service['power']
            
    result_ids.sort()
    print(' '.join(map(str, result_ids)))

solve()

算法及复杂度

  • 算法: 动态规划 (0/1 背包变种) + 回溯
  • 时间复杂度:
    • 填充 DP 表格需要两层循环,遍历所有服务和所有功耗预算,因此复杂度为
    • 回溯过程最多遍历 个服务,复杂度为
    • 总体时间复杂度由 DP 部分主导。
  • 空间复杂度:
    • 需要一个二维 DP 表来存储每个子问题的状态,空间大小为
全部评论

相关推荐

迷茫的大四🐶:看来已经准备换人了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务