题目地址
测试点(记录一下我遇到的坑)
1.测试点4和测试点5的提交时间一样,卡排队顺序。
2.有合法记录的、身体状况为 1 的申请人必须全部存下来,输出时再判重,不可以set直接存放判重,否则卡4.5.6测试点。
AC代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
using namespace std;
typedef pair<string, string> PSS;
struct Node
{
char name[15]; // 名字
char id[20]; // 身份证
int state; // 状态
int time; // 申请提交时间
int pos; // 排队序号
};
int d, p; // d天信息、间隔p天
map<string, int> mp; // 同一个id在第几天领取成功过、0表示没领取过
vector<Node> v; // 存放每天的有效申请信息(身份证合法)
vector<PSS> peo; // 身体状况为1的人都要存下来,输出时再判重(卡后三测试点)
set<PSS> S; // 输出时用于判重,患病信息是否输出过
bool check(char id[]) // 检查身份证是否合法
{
int len = strlen(id);
if (len != 18) return false;
else
{
for (int i = 0; i < len; i++)
if (id[i] < '0' || id[i] > '9')
return false;
}
return true;
}
bool cmp(Node a, Node b)
{
if (a.time != b.time) return a.time < b.time;
return a.pos < b.pos;
}
int main()
{
scanf("%d%d", &d, &p);
for (int i = 1; i <= d; i++) // 第i天
{
int t, s; // 申请、名额
scanf("%d%d", &t, &s);
v.clear(); // 把前一天的信息清空、只存当天的提交申请信息
Node node;
int hh, mm;
for (int j = 1; j <= t; j++) // 第j条申请信息
{
scanf("%s %s %d %d:%d", node.name, node.id, &node.state, &hh, &mm);
node.time = hh * 60 + mm;
node.pos = j;
if (check(node.id)) // 身份证合法
{
string str = node.id; // 将char转为string
if (!mp[str] || mp[str] + p < i) // 没领过或时间够了
v.push_back(node);
if (node.state) // 存下身体状况为1的人
{
string str1 = node.name, str2 = node.id;
peo.push_back({str1, str2}); // 先存下来,最后判重
}
}
}
sort(v.begin(), v.end(), cmp);
for (int j = 0; j < (int)v.size(); j++) // 输出当天可以领到口罩的人
{
string str = v[j].id;
if (!s) break; // 没口罩了
if (!mp[str] || mp[str] + p < i) // 满足条件
{
printf("%s %s\n", v[j].name, v[j].id);
mp[str] = i; // 标记为第i天领取过
s--;
}
}
}
// 不能用set直接存状态为1的人,必须输出的时候才判重(后三个测试点)
for (int i = 0; i < (int)peo.size(); i++)
{
if (!S.count(peo[i])) // 没输出过
{
printf("%s %s\n", peo[i].first.c_str(), peo[i].second.c_str());
S.insert(peo[i]);
}
}
return 0;
}