7-30 Table Tennis(難

題目

題意: 

一個乒乓球俱樂部有N張乒乓球桌對外開放。乒乓球桌編號爲1 ~ N。對任何一對運動員,如果他們到達時有空餘的乒乓球桌,他們會被分配到可用的編號最小的那張乒乓球桌。如果所有的桌子都被佔了,他們必須在隊列中等待。假設任何一對運動員最多隻能佔用球桌2小時。

你的任務是爲每個人計算他們在隊列中的等待時間,以及每張球桌一天服務的運動員數量。

由於俱樂部爲他們的VIP會員保留了一些VIP球桌,這使得這件事情變得稍微複雜了些。當一張VIP球桌對外開放時,隊列中的第一對VIP運動員將優先享有這張球桌的使用權。然而,如果隊列中沒有VIP運動員,下一對運動員可以使用這張球桌。另外,如果輪到了VIP運動員,但是沒有任何VIP球桌是可用的,他們就會像普通運動員一樣被安排

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
struct person {
	int arrive, start, time;
	bool vip;
} tempperson;
struct tablenode {
	int end = 8 * 3600, num;
	bool vip;
};
bool cmp1(person a, person b) {
	return a.arrive < b.arrive;
}
bool cmp2(person a, person b) {
	return a.start < b.start;
}
vector<person> player;
vector<tablenode> table;
void alloctable(int personid, int tableid) {
	if(player[personid].arrive <= table[tableid].end)//玩家到達時間早於桌子空閒時間 
		player[personid].start = table[tableid].end;
	else
		player[personid].start = player[personid].arrive;
	table[tableid].end = player[personid].start + player[personid].time;
	table[tableid].num++;
}
int findnextvip(int vipid) {
	vipid++;
	while(vipid < player.size() && player[vipid].vip == false) {
		vipid++;
	}
	return vipid;
}
int main() {
	int n, k, m, viptable;
	scanf("%d", &n);
	for(int i = 0; i < n; i++) {
		int h, m, s, temptime, flag;
		scanf("%d:%d:%d %d %d", &h, &m, &s, &temptime, &flag);
		tempperson.arrive = h * 3600 + m * 60 + s;
		tempperson.start = 21 * 3600;
		if(tempperson.arrive >= 21 * 3600)
			continue;
		tempperson.time = temptime <= 120 ? temptime * 60 : 7200;
		tempperson.vip = ((flag == 1) ? true : false);
		player.push_back(tempperson);
	}
	scanf("%d%d", &k, &m);
	table.resize(k + 1);
	for(int i = 0; i < m; i++) {
		scanf("%d", &viptable);
		table[viptable].vip = true;
	}
	sort(player.begin(), player.end(), cmp1);
	int i = 0, vipid = -1;
	vipid = findnextvip(vipid);
	while(i < player.size()) {
		int index = -1, minendtime = 999999999;
		for(int j = 1; j <= k; j++) {//找最先空出來的桌子 
			if(table[j].end < minendtime) {
				minendtime = table[j].end;
				index = j;
			}
		}
		if(table[index].end >= 21 * 3600)
			break;//健身館關門 
		// if(player[i].vip == true && i < vipid) {
		// 	i++;//前面已經出現過了 
		// 	continue;
		// }
		if(table[index].vip == true) {//最先空出來的桌子是VIP桌子 
			if(player[i].vip == true) {
				alloctable(i, index);//VIP人員分配VIP桌子 
				if(vipid == i)
					vipid = findnextvip(vipid);
				i++;
			} else {//非VIP人員,將VIP桌子分配給隊列中VIP人員 
				if(vipid < player.size() && player[vipid].arrive <= table[index].end) {
					alloctable(vipid, index);
					vipid = findnextvip(vipid);
				} else {//隊列中無VIP人員,則分配給普通人員 
					alloctable(i, index);
					i++;
				}
			}
		} else {
			if(player[i].vip == false) {//非VIP人員直接分配普通桌子 
				alloctable(i, index);
				i++;
			} else {//VIP人員分配最早空閒的VIP桌子 
				int vipindex = -1, minvipendtime = 999999999;
				for(int j = 1; j <= k; j++) {
					if(table[j].vip == true && table[j].end < minvipendtime) {
						minvipendtime = table[j].end;
						vipindex = j;
					}
				}//若存在最早的VIP空閒桌子 
				if(vipindex != -1 && player[i].arrive >= table[vipindex].end) {
					alloctable(i, vipindex);
					if(vipid == i)
						vipid = findnextvip(vipid);
					i++;
				} else {//不存在最早空閒的VIP桌子,找到分配最先空閒的普通桌子 
					alloctable(i, index);
					if(vipid == i)
						vipid = findnextvip(vipid);
					i++;
				}
			}
		}
	}
	sort(player.begin(), player.end(), cmp2);
	for(i = 0; i < player.size() && player[i].start < 21 * 3600; i++) {
		printf("%02d:%02d:%02d ", player[i].arrive / 3600, player[i].arrive % 3600 / 60, player[i].arrive % 60);
		printf("%02d:%02d:%02d ", player[i].start / 3600, player[i].start % 3600 / 60, player[i].start % 60);
		printf("%.0f\n", round((player[i].start - player[i].arrive) / 60.0));
	}
	for(int i = 1; i <= k; i++) {
		if(i != 1)
			printf(" ");
		printf("%d", table[i].num);
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章