【PAT甲级真题】- Table Tennis (30)

题目来源

Table Tennis (30) - PTA

Table Tennis (30) - 牛客

注意点:

  • 牛客的数据会弱一点,PTA 会强一点
  • 太多注意点了,思路吧
    这题从昨晚写到今晚,给个关注吧(哭),真的很难写。。。

题目描述

A table tennis club has N tables available to the public. The tables are numbered from 1 to N. For any pair of players, if there are some tables open when they arrive, they will be assigned to the available table with the smallest number. If all the tables are occupied, they will have to wait in a queue. It is assumed that every pair of players can play for at most 2 hours.

Your job is to count for everyone in queue their waiting time, and for each table the number of players it has served for the day.

One thing that makes this procedure a bit complicated is that the club reserves some tables for their VIP members. When a VIP table is open, the first VIP pair in the queue will have the priviledge to take it. However, if there is no VIP in the queue, the next pair of players can take it. On the other hand, if when it is the turn of a VIP pair, yet no VIP table is available, they can be assigned as any ordinary players.

输入描述:

Each input file contains one test case. For each case, the first line contains an integer N (<=10000) - the total number of pairs of players. Then N lines follow, each contains 2 times and a VIP tag: HH:MM:SS - the arriving time, P - the playing time in minutes of a pair of players, and tag - which is 1 if they hold a VIP card, or 0 if not. It is guaranteed that the arriving time is between 08:00:00 and 21:00:00 while the club is open. It is assumed that no two customers arrives at the same time. Following the players' info, there are 2 positive integers: K (<=100) - the number of tables, and M (< K) - the number of VIP tables. The last line contains M table numbers.

输出描述:

For each test case, first print the arriving time, serving time and the waiting time for each pair of players in the format shown by the sample. Then print in a line the number of players served by each table. Notice that the output must be listed in chronological order of the serving time. The waiting time must be rounded up to an integer minute(s). If one cannot get a table before the closing time, their information must NOT be printed.

##输入例子:

复制代码
9
20:52:00 10 0
08:00:00 20 0
08:02:00 30 0
20:51:00 10 0
08:10:00 5 0
08:12:00 10 1
20:50:00 10 0
08:01:30 15 1
20:53:00 10 1
3 1
2

输出例子:

复制代码
08:00:00 08:00:00 0
08:01:30 08:01:30 0
08:02:00 08:02:00 0
08:12:00 08:16:30 5
08:10:00 08:20:00 10
20:50:00 20:50:00 0
20:51:00 20:51:00 0
20:52:00 20:52:00 0
3 3 2

思路简介

这题不涉及算法,单纯的模拟,但是坑特别多,如果你过不了可能是下面的问题:

  1. 对于 vip 的分配
    • 如果 vip 进入队列时,有空的桌子,那么要尝试寻找 vip 桌,vip 会被分配到编号最小的 vip 桌,而不是编号最小的空桌子
    • 可能会有多张桌子在同一时刻空闲,这时,等待队列当中的分配顺序是先尝试给 vip 分配vip桌子,再考虑普通人
    • 如果没有 vip 桌子可以分配,那么 vip 会被视作普通人,轮到才分配
  2. round是四舍五入取整,不是向上取整(牛客没有这个样例,PTA第8个测试点是)
  3. 可能会出现 21 点来到的用户,此时不应把这种用户加入计算
  4. 可能会出现游玩时间大于 2 小时的用户,此时应当将他们的游玩时间取 2 小时(牛客上的最后一个样例,PTA的第 6 还是第 7 忘记了 )
  5. 输出按照服务时间排序,但是不要用 sort ,因为如果普通人和 vip 同时分配,如果有 vip桌子,vip 应当排在普通人之前
  6. PTA 上有格式要求,末尾不能有空格,同时要多输出一个换行

最后我的实现是采用 vip 和 ordinary 双队列,用 vector 维护

我没有设置等待时间,而是设置了每个桌子的空闲时间

这样如果有空闲的桌子就直接分配

没有空闲的桌子就要进入 vip 调度

遇到的问题

  1. round 想破头皮都没想到是四舍五入,一直错
  2. 没考虑空桌子分给 vip 的情况,因为题目中说 "For any pair of players, if there are some tables open when they arrive, they will be assigned to the available table with the smallest number.",我以为是 vip 在有空桌子的时候会直接分最小的,其实是先分 vip 桌子
  3. 没考虑同时有多个桌子空闲时,先分 vip

代码

cpp 复制代码
/**
 * https://www.nowcoder.com/pat/5/problem/4013
 * 模拟
 */
#include<bits/stdc++.h>
using namespace std;

int time_to_sec(string str){
    istringstream ss(str);
    int h,m,s;
    char c;
    ss>>h>>c>>m>>c>>s;
    return h*3600+m*60+s;
}

string sec_to_time(int sec){
    int h=sec/3600;
    int m=(sec%3600)/60;
    int s=sec%60;
    char buffer[10];
    sprintf(buffer,"%02d:%02d:%02d",h,m,s);
    return string(buffer);
}

struct People{
    int arr_time,play_time;
    int serve_time;
    People():arr_time(0),play_time(0),serve_time(-1){}
    People(int a,int p):arr_time(a),play_time(p),serve_time(-1){}
};

struct Table{
    int free_time,serve_num;
    int is_vip_table;

    Table():free_time(time_to_sec("08:00:00")),serve_num(0),is_vip_table(0){}
};

bool cmp(People a,People b){
    return a.arr_time<b.arr_time;
}

int peo_num,table_num,vip_table_num;
vector<People>ordinarys,vips,res;
Table table[107];
int end_time=time_to_sec("21:00:00");

void input(){
    cin>>peo_num;
    for(int i=0;i<peo_num;++i){
        string arr_time;
        int play_time,is_vip;
        cin>>arr_time>>play_time>>is_vip;
        play_time*=60;
        play_time = min(play_time, 7200);  // 必须添加
        if(time_to_sec(arr_time)>=end_time)continue;
        if(!is_vip)ordinarys.emplace_back(time_to_sec(arr_time),play_time);
        else vips.emplace_back(time_to_sec(arr_time),play_time);
    }

    cin>>table_num>>vip_table_num;
    for(int i=0;i<vip_table_num;++i){
        int t;cin>>t;
        table[t-1].is_vip_table=1;
    }

    sort(ordinarys.begin(),ordinarys.end(),cmp);
    sort(vips.begin(),vips.end(),cmp);
}

vector<int> find_table(People p){
    int mi=25*3600;

    //res1空闲的桌子,res2等待最小时间的桌子
    vector<int>res1,res2;
   
    for(int i=0;i<table_num;++i){
        if(table[i].free_time<=p.arr_time)
            res1.emplace_back(i);
        

        if(table[i].free_time<mi){
            mi=table[i].free_time;
            res2.clear();
            res2.emplace_back(i);
        }else if(table[i].free_time==mi)
            res2.emplace_back(i);
        
    }
    if(res1.size())return res1;//有空桌就返回空桌
    return res2;//没有空桌返回最快的桌子
}

int find_vip_table(vector<int>t){
    for(auto x:t){
        if(table[x].is_vip_table)
            return x;
    }
    return -1;
}

void assign(People p,int is_vip,int vt,vector<int>num){
    if(p.arr_time>=end_time)return;//9点之后来的

    if(table[num[0]].free_time<=p.arr_time){//有空桌
        if(is_vip&&vt!=-1){//是vip
            table[vt].serve_num++;
            table[vt].free_time=p.arr_time+p.play_time;
            p.serve_time=p.arr_time;
        }else {//不是vip=是vip但是没有vip桌子
            table[num[0]].serve_num++;
            table[num[0]].free_time=p.arr_time+p.play_time;
            p.serve_time=p.arr_time;
        }
    }else {//没有空桌子
        if(table[num[0]].free_time>=end_time)return;//最快的桌子大于9点,关店
        if(is_vip&&vt!=-1){//是vip
            table[vt].serve_num++;
            p.serve_time=table[vt].free_time;
            table[vt].free_time+=p.play_time;
        }else {//不是vip=是vip但是没有vip桌子
            table[num[0]].serve_num++;
            p.serve_time=table[num[0]].free_time;
            table[num[0]].free_time+=p.play_time;
        }
    }

    res.emplace_back(p);
}

void solve(){
    int lenv=vips.size(),leno=ordinarys.size();
    int kv=0,ko=0;

    while(kv<lenv&&ko<leno){
        int vip_arr_time=vips[kv].arr_time;
        int ord_arr_time=ordinarys[ko].arr_time;
        
        if(vip_arr_time<=ord_arr_time){//vip先到,直接给分桌
            vector<int>num=find_table(vips[kv]);
            int vt=find_vip_table(num);
            assign(vips[kv++],1,vt,num);
        }else {//普通先到,如果等待要先分给vip
            vector<int>num=find_table(ordinarys[ko]);
            if(table[num[0]].free_time<=ord_arr_time){//有空桌子,直接分
                assign(ordinarys[ko++],0,-1,num);
            }else {//没有空桌子
                int vt=find_vip_table(num);
                if(table[num[0]].free_time>=vip_arr_time&&vt!=-1){//vip在等待时来到
                    assign(vips[kv++],1,vt,num);
                }else {
                    assign(ordinarys[ko++],0,-1,num);
                }
            }
        }
    }

    while(kv<lenv){
        vector<int>num=find_table(vips[kv]);
        int vt=find_vip_table(num);
        assign(vips[kv++],1,vt,num);
    }

    while(ko<leno){
        vector<int>num=find_table(ordinarys[ko]);
        assign(ordinarys[ko++],0,-1,num);
    }

    for(auto p:res){
        if(p.serve_time==-1||p.serve_time>=end_time)continue;
        cout<<sec_to_time(p.arr_time)<<' '<<sec_to_time(p.serve_time);
        cout<<' '<<round((double)(p.serve_time-p.arr_time)/60)<<'\n';
    }

    for(int i=0;i<table_num;++i){
        cout<<table[i].serve_num;
        if(i!=table_num-1)cout<<' ';
    }
    cout<<'\n';
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //fstream in("in.txt",ios::in);cin.rdbuf(in.rdbuf());
    int T=1;
    //cin>>T;
    while(T--){
        input();
        solve();
    }
    return 0;
}
相关推荐
Irissgwe10 小时前
类与对象(三)
开发语言·c++·类和对象·友元
️是7810 小时前
信息奥赛一本通—编程启蒙(3395:练68.3 车牌问题)
数据结构·c++·算法
计算机安禾10 小时前
【c++面向对象编程】第24篇:类型转换运算符:自定义隐式转换与explicit
java·c++·算法
雪度娃娃10 小时前
转向现代C++——优先选用nullptr而不是0和NULL
开发语言·c++
我星期八休息10 小时前
Linux系统编程—基础IO
linux·运维·服务器·c语言·c++·人工智能·算法
故事和你9111 小时前
洛谷-【图论2-1】树5
开发语言·数据结构·c++·算法·动态规划·图论
paeamecium12 小时前
【PAT甲级真题】- String Subtraction (20)
数据结构·c++·算法·pat考试·pat
计算机安禾12 小时前
【c++面向对象编程】第25篇:仿函数(函数对象):重载operator()
开发语言·c++·算法
周末也要写八哥13 小时前
在C++中使用预定义宏
开发语言·c++·算法
小小编程路13 小时前
新手快速学 Python 极简速成指南
开发语言·c++·python