L2-046 天梯赛场的安排(STL模拟)
解题思路

太糟糕了,题干长,模拟复杂的一道题
本题有以下几个注意点:
-
每一轮都是对人数最多的学校分配赛场,所以要用一个优先队列。
-
题目要求计算每个学校要联系的监考老师数量,且题意要求为每个学校都要联系所在考场的监考老师,因此,需要计算出每个学校的学生安排在了几个考场
-
本题数据不够严谨,或者说本题要求较低,因为如果存在两个人数一样的学校,该怎么处理呢,题目没有明确说明,但是这对答案不会有影响,因为相等的几个元素实际上是等价的,最后统计的联系人数是不变的,但是实际上如果要考虑实际情况,这里一定是有问题的。但是为了方便,我们这里还是没考虑这一点
下面是赛场安排的过程:
-
把队头元素拿出来,记数量为cnt,如果cnt 大于等于 赛场容量,就要开一间新的赛场,把人放进去,如果 cnt 大于 赛场容量,说明还有剩下来的,就放回队中。这时候要记录联系人加一
-
如果cnt 小于 赛场容量,就找赛场容量大于等于cnt且编号最小的赛场安排进去。然后更新赛场的容量,记录联系人加一。更新容量的时候要把原来的赛场信息删除,更新后再插入。
-
如果找不到,就新开一个,这时候赛场必然是没排满的,所以直接更新赛场容量。
tip:本来我想使用二分查找,但是二分查找的前提是有序,但是这里的赛场不能排序,所以只能遍历了,当然可以使用set,但是那种复杂的容器我这里不想使用,因为太复杂了,jiangly_fan_fan_fan就是特别复杂的容器模拟,很难学会,尤其后面涉及到赛场容量的更新时,会很裹
ac✅️代码(也可以用数组代替结构体,不过看起来有点复杂)
//接下来的代码我参考了gemini,和jiangly_fan_fan_fan的,不过二者都有优缺点,本代码是我总结出最好理解的,不喜欢结构体的可以换成数组
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
struct School{
string name;
int teachers = 0;
int remain;
};
int main()
{
int n,m;
cin>>n>>m;
School sch[5010];
priority_queue<pair<int,int>> line;
for(int i = 0 ;i < n ; i++)
{
cin>>sch[i].name>>sch[i].remain;
line.push({sch[i].remain,i});//这里加入的是它在结构体数组中的索引
}
vector<int> rooms;//直接放容量即可,因为每个索引就是赛场编号
while(line.size())
{
auto [cnt,id] = line.top();
line.pop();
if(cnt >= m)
{
rooms.push_back(0);
sch[id].teachers ++;
if(cnt > m) line.push({cnt - m,id});
}
else
{
int index = -1;
for(int i = 0 ; i < rooms.size() ; i ++)
{
if(rooms[i] >= cnt)
{
index = i;
break;
}
}
if(index != -1)
{
rooms[index] -= cnt;
sch[id].teachers ++;
}
else
{
rooms.push_back(m - cnt);
sch[id].teachers ++;
}
}
}
for(int i = 0 ; i < n ; i++)
{
cout<<sch[i].name<<" "<<sch[i].teachers<<"\n";
}
cout<<rooms.size()<<endl;
return 0;
}

浙公网安备 33010602011771号