PAT_A1026
PAT甲级1026.
目录
A1026
题目
样例
输入:
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
思路和坑点
服务队列模拟,使用结构体数组的方式表示多个桌子,每个桌子结构体中包含桌子当前服务的结束时间,桌子服务的人数统计。顾客分成vip和非vip队列,这里利用map容器的成对儿存放,并且自身有序,因此用其表示顾客队列。
坑点
桌子服务的判定标准是,队列中有人,且已经在等候。桌子空闲的标志是该桌子当前服务结束时间小于等于当前的时间。
AC代码
#include<bits/stdc++.h>
using namespace std;
#define st 8*3600
#define ed 21*3600
typedef struct table{ //桌子结构体
int edtime,cnt,tag; //当前服务的结束时间,服务人数统计,vip标记
table():edtime(st),cnt(0),tag(0){} //初始化
}Table;
void Print(int i){
printf("%02d:%02d:%02d",i/3600,i/60%60,i%60); //打印时间
}
vector<Table> T; //桌子的数组
map<int,int> mpo,mpv; //map表示的顾客服务队列
void check(int j,int time,map<int,int> &mp){ //使用传引用的方式,对不同的队列进行判断是都要从中取出顾客进行服务
if(mp.size()){ //非空
auto it=mp.begin();
if(it->first<=time){ //队头顾客已经在等待,进行服务,打印并更新队列参数
T[j].edtime=time+it->second;
T[j].cnt++;
Print(it->first); putchar(' ');
Print(time); putchar(' ');
printf("%d\n",(time-it->first+30)/60);
mp.erase(it);
}
}
}
int main(void){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt","r",stdin);
#endif
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){ //读入
int hh,mm,ss,cost,tag;
scanf("%d:%d:%d %d %d",&hh,&mm,&ss,&cost,&tag);
cost=cost>120?120*60:cost*60;
if(tag==0)
mpo[hh*3600+mm*60+ss]=cost; //普通用户入队
else
mpv[hh*3600+mm*60+ss]=cost; //vip用户入队
}
int k,m;
scanf("%d %d",&k,&m);
T.resize(k);
for(int i=0;i<m;i++){ //vip桌子的标记
int temp;
scanf("%d",&temp);
T[temp-1].tag=1;
}
for(int i=st;i<ed;i++){
for(int j=0;j<k;j++){ //优先遍历一遍为vip顾客进行服务判定
if(T[j].edtime<=i&&T[j].tag==1){
check(j,i,mpv);
if(mpv.size()==0) break; //vip服务全部完成时,提前结束循环
}
}
for(int j=0;j<k;j++){ //安排了vip之后,全员进行判定
if(T[j].edtime<=i){
if(mpo.size()&&mpv.size()){ //如果都不空,取来的早的进行判定
auto it=mpo.begin(),itv=mpv.begin();
if(it->first<itv->first)
check(j,i,mpo);
else if(it->first>itv->first)
check(j,i,mpv);
}
else if(mpo.size()) //如果有一个空,非空的进行判定
check(j,i,mpo);
else if(mpv.size())
check(j,i,mpv);
else break; //都空则,提前结束,表示顾客已经服务完毕
}
}
if(mpo.size()==0&&mpv.size()==0) break;
}
for(int i=0;i<k;i++){ //打印服务人数
if(i) putchar(' ');
printf("%d",T[i].cnt);
}
return 0;
}