PAT甲级1026——Table Tennis

#include<iostream>
#include<map>
#include<string>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
int close_time=75600;
struct player{
	int arrive_time;
	int play_time;
	int flag;
}P;
struct table{
	int accT;
	int flag;
	table(){
		accT=28800;
		flag=0;
	}
};
vector<player> usul_players;
vector<player> vip_player;
bool mycmp(player a,player b){
	return a.arrive_time<b.arrive_time;
}
int main(){
	int N;
	scanf("%d",&N);
	int h,m,s;
	for(int i=0;i<N;++i){
		scanf("%d:%d:%d %d %d",&h,&m,&s,&P.play_time,&P.flag);
        if(P.play_time>120) P.play_time=120;
		P.arrive_time=h*3600+m*60+s;
		if(P.flag)
			vip_player.push_back(P);
		else 
			usul_players.push_back(P);
	}
	P.arrive_time=1e8;
	vip_player.push_back(P);
	usul_players.push_back(P);
	sort(usul_players.begin(),usul_players.end(),mycmp);
	sort(vip_player.begin(),vip_player.end(),mycmp);
	int K,M;
	scanf("%d%d",&K,&M);
	table tables[101];
	for(int i=0;i<M;++i){
		int table_num;
		scanf("%d",&table_num);
		tables[table_num].flag=1;
	}
	int serve_num[101]={0};
    int cnt=0;
	while(cnt<N){
		int cus_idx,table_idx=-1;
		//选人;
		cus_idx=vip_player[0].arrive_time<usul_players[0].arrive_time?1:0;
		if(cus_idx==1){
			for(int i=1;i<=K;++i)
				if(tables[i].accT<=vip_player[0].arrive_time)
					if(tables[i].flag==1){
						table_idx=i;
						break;
					}else if(table_idx==-1) table_idx=i;
			if(table_idx==-1){     //无可用的桌子;
                table_idx=1;
				for(int i=2;i<=K;++i)
					if(tables[i].accT<tables[table_idx].accT) table_idx=i;
					else if(tables[i].accT==tables[table_idx].accT&&tables[i].flag>tables[table_idx].flag) table_idx=i;
            }
		}else{
			for(int i=1;i<=K;++i)
				if(tables[i].accT<=usul_players[0].arrive_time){
					table_idx=i;
					break;
				}
			if(table_idx==-1){
				table_idx=1;
				for(int i=2;i<=K;++i)
					if(tables[i].accT<tables[table_idx].accT) table_idx=i;
                   // else if(tables[i].accT==tables[table_idx].accT&&tables[i].flag<tables[table_idx].flag) table_idx=i;
                   //如果出现普通客户当前没有可用的球桌,寻找最早可用球桌的过程中,有一个vip球桌和一个普通球桌在未来的同一个时间点可用,而且,这个可用的vip球桌可用时有vip客户在等候,到底是先打印普通客户,还是先打印vip客户?
				if(tables[table_idx].flag==1&&vip_player[0].arrive_time<=tables[table_idx].accT)
					cus_idx=1;
			}
		}
        P=cus_idx==0?usul_players[0]:vip_player[0];
        int serve_p=max(tables[table_idx].accT,P.arrive_time);
		if(serve_p>=close_time) break;
		++serve_num[table_idx];
		printf("%02d:%02d:%02d %02d:%02d:%02d %.0lf\n",P.arrive_time/3600,P.arrive_time/60%60,P.arrive_time%60,serve_p/3600,serve_p/60%60,serve_p%60,round((serve_p-P.arrive_time)/60.0));
		tables[table_idx].accT=serve_p+P.play_time*60;
		if(cus_idx==0) usul_players.erase(usul_players.begin());
		else vip_player.erase(vip_player.begin());
        ++cnt;
	}//while(非空);
	for(int i=1;i<=K;++i){
		printf("%d",serve_num[i]);
        if(i<K)
        printf(" ");
    }
	system("pause");
	return 0;
}

总体思路:
1、将客户分为VIP客户队和普通客户队,然后在两种队后各添加一个到达时间为1e8的虚拟客户,防止出现队空的情况,简化讨论情形。
2、判断两个队首的客户中,那个客户更早到来·:
a、如果是VIP客户更早到来,再分为两种情况讨论:
如果客户到来时有空余的桌子,那么如果该桌子为VIP桌,那就选择最小的空闲VIP,否则,选择最小的普通桌;
否则,客户到来时没有空桌子,客户需要等候,那就选择最早可获得的 且编号最小的任意桌。
b、同理,当普通客户更早到来时,也要分为两种情形讨论:
如果客户到来时有空余桌,选择编号最小的可用任意桌(即使是VIP桌也无所谓,因为既然桌子可用,那桌子open的时间就在该普通客户到来之前,而普通客户又比后面的客户早,所以VIP桌可用时,可以保证没有VIP客户等候);
否则·,客户到来时没有空桌,客户等候,选择最早可获得的桌子,如果是普通桌,那就等候该普通桌open,普通客户使用,如果是·VIP桌先open,那就要判断一下VIP桌可用时,是否有VIP客户在等候,如果是的话,那VIP客户要先被服务,否则VIP桌才能被这个普通客户使用。(关于此处,还有个点比较模糊,如果最早可得的桌子有两个,一个是VIP桌,一个是普通桌,且VIP桌可用时队列中有VIP客户在等候,那到底是先输出普通客户的使用时间,还是VIP客户的使用时间?PS:我题目中是有VIP桌最先可用,特判VIP客户,先输出的VIP)
3、注意的点:题目说没在21:00前被服务的都不能服务,所以在while()循环中途退出的条件要写为判断服务时间serve_time>=21:00时break;不能是桌子可用时间>=21:00,防止出现21:00到来的客户,因为虽然有时桌子可用,但是没有客户。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值