pat 1026 Table Tennis 模拟

地址:https://pintia.cn/problem-sets/994805342720868352/problems/994805472333250560

pat的模拟是又坑又难写,不想写模拟,老出坑;
所以网上查了一下,别人写的代码较少的模拟;
坑点:
(1)每个乒乓球台的服务时间在8:00~21:00之间,超过21:00的不再服务
(2)等待队列中,VIP的优先级体现在当有空VIP专用球台时,VIP客户可以直接使用,而不管前面是否有普通客户在等待
(3)最为重要的一点,当有普通球台和VIP球台时,VIP客户遵循选择最小编号的VIP球台(VIP就要这么任性),而非编号最小的球台;普通客户遵循选择最小的球台
(4)每个人的服务时间在2小时之内,超过2小时的按2小时处理;
(5)注意最后计算等待时间时采用的是四舍五入

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second

//存储每个节点的到达时间,等待时间,客户等级
struct Node{
    int time,last,f;
}p[10005];
//存储到达时间,服务时间,等待时间长度
struct result{
    int t1,t2,wait;
}res[10005];
vector<Node>v[2]; //存储不同等级客户的情况
int ok[105],vip[105],serve[105];
int n,m,k;
bool cmp(const Node &p,const Node &q){
    return p.time < q.time;
}
bool cmp1(const result &p,const result &q){
    return p.t2 < q.t2;
}

//根据客户等级找到对应的桌子
int Find(int tm,int f)
{
    int MIN = inf,ans = 0;
    for(int i = 1;i <= m;++i){
        if(f && !vip[i]) continue;
        if(ok[i] < tm){
            ans = i;
            break;
        }else if(ok[i] < MIN){
            ans = i;
            MIN = ok[i];
        }
    }
    return ans;
}


int main()
{
    int n;
    cin >> n;
    for(int i = 0;i < n;++i){
        int a,b,c;
        scanf("%d:%d:%d %d %d",&a,&b,&c,&p[i].last,&p[i].f);
        p[i].time = a * 3600 + b * 60 + c;
        if(p[i].f) v[1].pb(p[i]);
        else v[0].pb(p[i]);
    }
    p[n].time = inf;
    p[n + 1].time = inf;
    v[0].pb(p[n]); v[1].pb(p[n + 1]);
    sort(v[0].begin(),v[0].end(),cmp);
    sort(v[1].begin(),v[1].end(),cmp);
    cin >> m >> k;
    //初始化起始时间
    for(int i = 1;i <= m;++i){
        ok[i] = 8 * 60 * 60;
    }
    memset(vip,0,sizeof(vip));
    for(int i = 1;i <= k;++i){
        int a;
        cin >> a;
        vip[a] = 1;
    }
    int num = 0;
    int i = 0,j = 0;
    //每次从v[0],v[1]即普通客户和vip客户中选一个分配,题中已说明同一个时间不会有多个客户到达
    //得到vip_table是为了当分配的是vip客户,那么如果ok[vip_table] <= v[1][pos].time,应该优先分配这一桌
    //尽管得到的ok[id] <= ok[vip_table]
    while(true){
        int tm1 = v[0][i].time,tm2 = v[1][j].time;
        int id = Find(min(tm1,tm2),0),who;
        int vip_table = Find(tm2,1);
        //如果找到的桌子的时间在21点之后或者到达时间在21点之后,那么就得就到终点了
        if(ok[id] >= 21 * 60 * 60 || min(tm1,tm2) >= 21 * 60 * 60) break;
        if(!vip[id]) who = v[0][i].time < v[1][j].time ? 0 : 1;
        else who = v[1][j].time < max(ok[id],v[0][i].time) ? 1 : 0;
        int pos = who == 0 ? i : j;
        if(who == 1 && vip_table && ok[vip_table] <= v[1][pos].time) id = vip_table;
        res[num].t1 = v[who][pos].time;
        res[num].t2 = max(ok[id],v[who][pos].time);
        res[num].wait = res[num].t2 - res[num].t1;
        ok[id] = res[num].t2 + min(v[who][pos].last,120) * 60;
        serve[id]++;
        if(who == 0) i++;
        else j++;
        num++;
    }
    sort(res,res + num,cmp1);
    for(int i = 0;i < num;++i){
        printf("%02d:%02d:%02d %02d:%02d:%02d %d\n",res[i].t1/3600,res[i].t1%3600/60,res[i].t1%60,res[i].t2/3600,res[i].t2%3600/60,res[i].t2%60,(res[i].wait+30)/60);
    }
    for(int i = 1;i < m;++i) cout << serve[i] << " ";
    cout << serve[m] << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值