1026. Table Tennis (30)
网上代码很多,但感觉偏长。我的想法是维护了两个队列vp代表vip队列和pp代表普通队列,use[i]表示第i张桌子还需使用的时间。
3个注意点别人都提过了:
1.很多空桌,vip先选vip桌子
2.顾客玩的时间不超过2小时
3.时间四舍五入(只要+30s)
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=10010,M=101,tbegin=8*3600,tend=21*3600;
int num[M],use[M],vip[M];
struct node{
int time,play,tag,stime;
}p[N],vp[N],pp[N];
int cmp(node a,node b){
return a.time<b.time;
}
int cmp1(node a,node b){
return a.stime<b.stime;
}
void print(int sec){
printf("%02d:%02d:%02d ",sec/3600,(sec%3600)/60,sec%60);
}
int main(){
int n,k,m;
scanf("%d",&n);
for(int i=0,hh,mm,ss;i<n;i++){
scanf("%d:%d:%d %d %d",&hh,&mm,&ss,&p[i].play,&p[i].tag);
p[i].time=hh*3600+mm*60+ss;
if(p[i].play>120) p[i].play=120;//不超过2小时
p[i].play*=60;
}
scanf("%d %d",&k,&m);//k张桌子m张VIP
for(int i=0,v;i<m;i++){
scanf("%d",&v);
vip[v]=1;
}
sort(p,p+n,cmp);
int vn=0,pn=0;
for(int i=0;i<n;i++){
if(p[i].tag==1) vp[vn++]=p[i];
else pp[pn++]=p[i];
}
vp[vn].time=tend;//设置队列末尾
pp[pn].time=tend;
//开始模拟时间t
int next=0,vnext=0,useNum=0,vipNum=0;
for(int t=tbegin;t<tend;t++){
//桌子使用情况更新
for(int i=1;i<=k;i++){
if(!use[i]) continue;
if(--use[i]==0){
if(vip[i]) vipNum--;
useNum--;
}
}
//安排vip
while(vp[vnext].time<=t&&vipNum<m){//可以放入vip
vp[vnext].stime=t;
for(int i=1;i<=k;i++)
if(vip[i]&&!use[i]){
use[i]=vp[vnext].play;
num[i]++;
break;
}
vipNum++,useNum++,vnext++;
}
//安排全部--到达时间顺序
while((pp[next].time<=t||vp[vnext].time<=t)&&useNum<k){
int i;
for(i=1;i<=k;i++)
if(!use[i]) break;
if(pp[next].time<vp[vnext].time){
pp[next].stime=t;
use[i]=pp[next++].play;
}
else{
vp[vnext].stime=t;
use[i]=vp[vnext++].play;
}
if(vip[i]) vipNum++;
useNum++,num[i]++;
}
}
//组装两个队列
int cnt=0;
for(int i=0;i<vn;i++)
p[cnt++]=vp[i];
for(int i=0;i<pn;i++)
p[cnt++]=pp[i];
sort(p,p+cnt,cmp1);
//输出
for(int i=0;i<cnt;i++){
if(p[i].stime==0) continue;
print(p[i].time);
print(p[i].stime);
printf("%d\n",(30+p[i].stime-p[i].time)/60);//4舍5入
}
printf("%d",num[1]);
for(int i=2;i<=k;i++)
printf(" %d",num[i]);
printf("\n");
}