#P3869. 第3题-最大客户数
-
2000ms
Tried: 121
Accepted: 36
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 的客户分配到第三个数据中心