1026. Table Tennis (30)

    将排队的人按照到达的时间排序,然后开始轮询,会有四种情况:

  • 桌子是VIP,人是VIP,则直接分配
  • 桌子不是VIP,人也不是VIP,则直接分配
  • 桌子是VIP,人不是VIP,则往后找,是否存在一个VIP,且其到达时间早于该桌子的可用时间,找到则给VIP,当前的人继续等待,找不到这样的VIP,则把该桌子给当前用户
  • 桌子不是VIP,人是VIP,则检查桌子,是否还存在一张VIP桌子也空闲着,如果有这样一张VIP桌子,则将VIP桌子分给该VIP用户,如果没有VIP桌子闲着,则该VIP用该桌子。

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <tuple>

using namespace std;

#define INF (~(1<<31))

struct Player{
	int arrive, play, serve, leave, wait, tag;

	Player(int a, int p, int t) : arrive(a), play(p), serve(INF), leave(INF), wait(INF), tag(t){}

	bool operator < (const Player& rhs) const{
		return arrive < rhs.arrive;
	}
};

struct Table{
	int leave;
	int cnt;
	int tag;

	Table() : leave(8 * 3600), cnt(0), tag(0){}
};

int time2sec(int hh, int mm, int ss){
	return hh * 3600 + mm * 60 + ss;
}

tuple<int,int,int> sec2time(int n){
	return make_tuple(n/3600, (n%3600)/60, (n%3600)%60);
}

int main(){
	int n;
	scanf("%d", &n);

	vector<Player> users;
	for (int i = 0; i < n; ++i){
		int hh, mm, ss, p, tag;
		scanf("%d:%d:%d %d %d", &hh, &mm, &ss, &p, &tag);
		users.emplace_back(time2sec(hh, mm, ss), min(p*60, 2*60*60), tag);
	}

	sort(begin(users), end(users));

	int k, m;
	scanf("%d%d", &k, &m);
	vector<Table> tables(k);
	for (int i = 0; i < m; ++i){
		int num;
		scanf("%d", &num);  num--;
		tables[num].tag = 1;
	}


	int i;
	for (i = 0; i < n; ++i){
		// if the player has been processed, continue
		if (users[i].serve != INF) continue;

		// find the available table with the smallest number
		int j = -1, minLeave = INF;
		for (int x = 0; x < k; ++x){
			if (minLeave > tables[x].leave){
				minLeave = tables[x].leave;
				j = x;
			}
		}

		// if the minLeave table >= 21:00:00 or the current player's arrive time >= 21:00:00, break;
		if(tables[j].leave >= 21*3600 || users[i].arrive >= 21*3600) break;

		int u = i, t = j;

		// table is vip && player is not vip
		if (tables[j].tag && !users[i].tag){
			int ii = -1;
			for (int x = i + 1; x < n; ++x){
				if (users[x].serve == INF && users[x].tag && users[x].arrive <= tables[j].leave){
					ii = x;
					break;
				}
			}

			if(ii != -1){
				--i;    // the current player need wait
				u = ii;
			}
		}else if (!tables[j].tag && users[i].tag){ // table is not vip && player is vip
			int jj = t;
			for (int x = j + 1; x < k; ++x){
				if (tables[x].tag && tables[x].leave <= users[i].arrive){
					jj = x;
					break;
				}
			}

			t = jj;
		}


		if (tables[t].leave < users[u].arrive){
			tables[t].leave = users[u].arrive + users[u].play;
		}
		else{
			tables[t].leave += users[u].play;
		}

		users[u].leave = tables[t].leave;
		users[u].serve = users[u].leave - users[u].play;
		users[u].wait = users[u].serve - users[u].arrive;
		tables[t].cnt++;
	}

	sort(begin(users), end(users), [](const	Player& lhs, const Player& rhs){
		if (lhs.serve != rhs.serve) return lhs.serve < rhs.serve;
		else return lhs.arrive < rhs.arrive;
	});

	for (size_t i = 0; i < users.size(); ++i){
		if (users[i].serve > 21 * 3600) continue;

		int hh1, mm1, ss1, hh2, mm2, ss2;
		tie(hh1, mm1, ss1) = sec2time(users[i].arrive);
		tie(hh2, mm2, ss2) = sec2time(users[i].serve);

		int w = (int)round(users[i].wait / 60.0);
		printf("%02d:%02d:%02d %02d:%02d:%02d %d\n", hh1, mm1, ss1, hh2, mm2, ss2, w);
	}

	for(size_t i = 0; i < tables.size(); ++i){
		if(i) printf(" ");
		printf("%d", tables[i].cnt);
	}

	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值