#P3869. 第3题-最大客户数
          
                        
                                    
                      
        
              - 
          
          
                      2000ms
            
          
                      Tried: 88
            Accepted: 32
            Difficulty: 5
            
          
          
          
                       所属公司 : 
                              华为
                                
            
                        
              时间 :2025年10月10日(留学生)-非AI方向(通软&嵌软&测试&算法&数据科学)
                              
                      
          
 
- 
                        算法标签>贪心算法          
 
第3题-最大客户数
本题是NP-hard问题,无法在线性时间得到最优解。由于数据范围较大,题解给出近似解法First-Fit Decreasing。
解题思路
给定多个数据中心的服务器容量 data_centers[i],以及多个客户的服务器需求 customer_requests[j]。一个客户必须完全放到同一个数据中心中,数据中心可以服务多个客户,只要总占用不超过其容量。目标是最大化能被完全服务的客户数量。
核心思路:
将客户按照需求从小到大排序,优先满足小需求;同时用一个“有序可更新的容器”保存当前各数据中心的“剩余容量”。对每个客户需求 r,在容器中找到最小的且≥r 的剩余容量(best-fit)。若找到:
- 把该容量取出,分配 
r后若仍有剩余rest = cap - r,再把rest放回容器; - 计数加一。 若找不到,跳过该客户。
 
相关算法与数据结构:
- 贪心(按需求升序 + 最小可行仓位分配,Best-Fit)
 - 有序容器:C++ 用 
multiset,Java 用TreeMap(作为“有序多重集合”),Python 用排序列表 +bisect二分插入/查找。 
代码实现
Python
from bisect import bisect_left, insort
def max_customers(data_centers, customer_requests):
    # 剩余容量有序表
    remains = sorted(data_centers)
    # 客户需求升序
    reqs = sorted(customer_requests)
    count = 0
    for r in reqs:
        # 找到第一个 >= r 的剩余容量位置(best-fit)
        pos = bisect_left(remains, r)
        if pos == len(remains):
            # 没有数据中心能容纳该客户,跳过
            continue
        cap = remains.pop(pos)       # 取出该容量
        rest = cap - r               # 分配后的剩余
        if rest > 0:
            insort(remains, rest)    # 仍有剩余则放回有序表
        count += 1
    return count
def main():
    # 读取输入(四行)
    n = int(input().strip())
    data_centers = list(map(int, input().strip().split()))
    m = int(input().strip())
    customer_requests = list(map(int, input().strip().split()))
    # 计算并输出
    print(max_customers(data_centers, customer_requests))
if __name__ == "__main__":
    main()
Java
import java.util.*;
public class Main {
    static int maxCustomers(int[] dataCenters, int[] customerRequests) {
        // TreeMap 作为“有序多重集合”:key = 剩余容量,value = 该容量出现次数
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for (int cap : dataCenters) {
            map.put(cap, map.getOrDefault(cap, 0) + 1);
        }
        Arrays.sort(customerRequests); // 客户需求升序
        int count = 0;
        for (int r : customerRequests) {
            // 找到最小的 >= r 的容量
            Integer key = map.ceilingKey(r);
            if (key == null) {
                // 无法满足该客户
                continue;
            }
            // 使用该容量一次
            int c = map.get(key);
            if (c == 1) map.remove(key);
            else map.put(key, c - 1);
            int rest = key - r; // 分配后的剩余
            if (rest > 0) {
                map.put(rest, map.getOrDefault(rest, 0) + 1);
            }
            count++;
        }
        return count;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 读取输入(四行)
        int n = Integer.parseInt(sc.nextLine().trim());
        String[] a = sc.nextLine().trim().split("\\s+");
        int[] dataCenters = new int[n];
        for (int i = 0; i < n; i++) dataCenters[i] = Integer.parseInt(a[i]);
        int m = Integer.parseInt(sc.nextLine().trim());
        String[] b = sc.nextLine().trim().split("\\s+");
        int[] customerRequests = new int[m];
        for (int i = 0; i < m; i++) customerRequests[i] = Integer.parseInt(b[i]);
        // 计算并输出
        System.out.println(maxCustomers(dataCenters, customerRequests));
    }
}
C++
#include <bits/stdc++.h>
using namespace std;
int max_customers(const vector<int>& data_centers, const vector<int>& customer_requests) {
    multiset<int> ms;                    // 有序多重集合保存剩余容量
    for (int x : data_centers) ms.insert(x);
    vector<int> reqs = customer_requests;
    sort(reqs.begin(), reqs.end());      // 客户需求升序
    int cnt = 0;
    for (int r : reqs) {
        // 找到第一个 >= r 的容量(best-fit)
        auto it = ms.lower_bound(r);
        if (it == ms.end()) {
            // 没有数据中心可以容纳该客户
            continue;
        }
        int cap = *it;
        ms.erase(it);                    // 取出该容量
        int rest = cap - r;              // 分配后的剩余
        if (rest > 0) ms.insert(rest);   // 仍有剩余则放回
        cnt++;
    }
    return cnt;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    // 读取输入(四行)
    int n; 
    cin >> n;
    vector<int> data_centers(n);
    for (int i = 0; i < n; ++i) cin >> data_centers[i];
    int m; 
    cin >> m;
    vector<int> customer_requests(m);
    for (int i = 0; i < m; ++i) cin >> customer_requests[i];
    // 计算并输出
    cout << max_customers(data_centers, customer_requests) << "\n";
    return 0;
}
        题目内容
业务背景:
假设你是一家云服务提供商的工程师,负责优化云资源的分配。公司有多个数据中心,每个数据中心有不同数量的服务器。现在有一些新的客户需要分配服务器资源。每个客户对服务器的需求量不同,而每个数据中心的服务器数量有限。你的任务是尽可能满足更多客户的需求,要求:同一个数据中心的服务器可以分配给多个客户使用,一个客户的需求只能分配到其中一个数据中心。
问题: 给定一个列表 data_centers,表示每个数据中心的服务器数量,和一个列表 customer _requests,表示每个客户的服务器需求量。你需要设计一个算法,将客户分配到不同的数据中心,使得满足客户需求的数量最大。
输入描述
输入四行:
第一行是一个整数,表示数据中心大小
第二行为一个数组,表示每个数据中心的服务器数量,用空格分割
第三行是一个整数,表示客户总数
第四行为一个数组,表示每个客户的服务器需求量,用空格分割
输入范围:
1<=len(data_centers)<=1000
1<=len(customer_requests)<=1000
1<=data_centers[i]<=10000
1<=customer_requests[i]<=10000
输出描述
一个整数,表示最多可以满足的客户数量。
如果所有客户都不满足需求,则返回客户数为 0 。
样例1
输入
3
1 2 3
3
100 2 300
输出
1
说明
在这个样例中,每个数据中心的服务器数量都非常少,分别为 1、2 和 3 台而每个客户的需求量,分别为 100、2 和 300 台服务器
只能能够满足一个客户的需求,输出为 1
样例2
输入
3
10 20 30
4
5 10 15 25
输出
4
说明
可以将需求为 5 的客户分配到第二个数据中心
将需求为 10 的客户分配到第一个数据中心
将需求为 15 的客户分配到第二个数据中心
将需求为 25 的客户分配到第三个数据中心