1026. Table Tennis (30)

本文介绍了一种乒乓球桌分配算法,该算法通过维护VIP和普通玩家的队列,并使用优先级策略来分配有限数量的乒乓球桌。文章详细展示了算法实现过程,包括如何处理顾客到达时间、选择桌子类型以及游戏时长等细节。

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");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值