PAT 1026 Table Tennis

#include<iostream>

#include<cstdio>

#include<string>

#include<cstring>

#include<queue>

#include<vector>

#include<cmath>

#include<iomanip>

#include<algorithm>

using namespace std;



const int MAX_N = 10000+5;

const int MAX_TABLE = 100+5;

const int OFF_TIME = 13*60*60;

const int TWO_HOUR = 2*60*60; //每组最多只能占用桌子2个小时的时间。



struct Player

{

	int iArrTime;  //到达的时间

	int iPlayTime;  //运动的时间

	int iWaitTime; //等待的时间

	bool isServed;//是否在21:00之前得到桌子

	bool isVip; //是否为VIP会员

};

Player arrPlayers[MAX_N];



struct Tables

{

	int iAvaiTime;//桌子available的时间

	int iCount;//服务了多少组

	bool isVip; //是否为VIP桌子

};

Tables arrTables[MAX_TABLE];



int N,K,M; //N个players,K张桌子,M张VIP桌子



//按到达时间进行排序

bool lessCmp(Player p1, Player p2)

{

	return p1.iArrTime < p2.iArrTime;

}



//按服务时间先后进行排序

bool lessCmp2(Player p1, Player p2)

{

	return (p1.iWaitTime+p1.iArrTime) < (p2.iWaitTime+p2.iArrTime);

}



//将07:55:00形式的时间转换为相对08:00的时间,单位:秒。

//如果早于8点,则返回负数。

int getRelTime(char *chTime)

{

	int iRes;

	int h = (chTime[0] - '0')*10 + chTime[1]-'0';

	int m = (chTime[3] - '0')*10 + chTime[4]-'0';

	int s = (chTime[6] - '0')*10 + chTime[7]-'0';

	int iEight = 8*60*60;

	int iNow = (h*60 + m)*60 + s;

	iRes = iNow - iEight;

	return iRes;

}





//数据输入和初始化

void inputData()

{

	int i,j,iTabId,iPlayTimeMins;

	cin>>N;

	char chArriveTime[15];



	for(i=1; i<=N; i++)

	{

		cin>>chArriveTime;

		arrPlayers[i].iArrTime = getRelTime(chArriveTime);

		cin>>iPlayTimeMins;

		//将分钟转换为妙

		arrPlayers[i].iPlayTime = iPlayTimeMins*60;

		cin>>arrPlayers[i].isVip;

		arrPlayers[i].iWaitTime = 0;

		arrPlayers[i].isServed = false;

	}

	cin>>K>>M;

	for(i=1; i<=K; i++)

	{

		arrTables[i].iAvaiTime = 0;

		arrTables[i].iCount = 0;

		arrTables[i].isVip = false;

	}

	for(j=1; j<=M; j++)

	{

		cin>>iTabId;

		arrTables[iTabId].isVip = true;

	}

}



//得到一个空闲的桌子,遍历K个桌子,找到桌子的available时间小于iCurTime且编号最小的桌子。

//如果所有的桌子的avaliable时间都大于iCurTime,则找到avaliable最早的时间;

//注意编号为1到K。

int getAnFreeTab(int K, int iCurTime)

{

	int i=0;

	for(i=1; i<=K; i++)

		if(arrTables[i].iAvaiTime < iCurTime)

			return i;

	int iAvaTimeMin = arrTables[1].iAvaiTime;

	int iTabId = 1;

	for(i=2; i<=K; i++)

		if(arrTables[i].iAvaiTime < iAvaTimeMin)

		{

			iAvaTimeMin = arrTables[i].iAvaiTime;

			iTabId = i;

		}

	return iTabId;

}



int max(int a,int b)

{

	return a>b?a:b;

}



//窗口iWinId处理完一个客户后,需要更新窗口available最早的时间 

void updateWinsInfo(int iTableId,int iPlayerId)

{

	int iCurTime = max(arrTables[iTableId].iAvaiTime,arrPlayers[iPlayerId].iArrTime);



	if(arrPlayers[iPlayerId].iPlayTime <= TWO_HOUR)//处理的时间不能超过一个小时

		arrTables[iTableId].iAvaiTime =iCurTime + arrPlayers[iPlayerId].iPlayTime;

	else

		arrTables[iTableId].iAvaiTime =iCurTime + TWO_HOUR;

}



//将iPlayerId客户放到桌子iTableId进行处理

void processAnCus(int iTableId, int iPlayerId)

{

	//开始就空闲的桌子

	if(arrTables[iTableId].iAvaiTime == 0) 

	{

		arrPlayers[iPlayerId].iWaitTime = 0;

		arrPlayers[iPlayerId].isServed = true;

		arrTables[iTableId].iCount++;

	}

	else//处理过客户的桌子

	{

        if(arrTables[iTableId].iAvaiTime >= OFF_TIME) //未在关门前得到桌子

		{

			arrPlayers[iPlayerId].iWaitTime = 0;

			arrPlayers[iPlayerId].isServed = false;

		}

		else

		{

			if(arrTables[iTableId].iAvaiTime <= arrPlayers[iPlayerId].iArrTime)

				arrPlayers[iPlayerId].iWaitTime = 0;

			else

				arrPlayers[iPlayerId].iWaitTime = arrTables[iTableId].iAvaiTime - arrPlayers[iPlayerId].iArrTime;

			arrPlayers[iPlayerId].isServed = true;

			arrTables[iTableId].iCount++;

		}

	}

	updateWinsInfo(iTableId,iPlayerId);

}





//获得在当前时间的等待队列的一个VIP用户的下标,从iPlayerId开始查找;如果等待队列中没有VIP用户,则返回-1;

int getAnVipPlayer(int iPlayerId, int iCurTime)

{

	for(int i=iPlayerId; i<=N; i++)

		if(arrPlayers[i].isVip && arrPlayers[i].iArrTime<iCurTime)

			return i;

	return -1;

}



//对在等待队列上的客户进行处理

void process()

{

	//下标从1开始,所以sort时要注意。

	sort(arrPlayers+1,arrPlayers+N+1,lessCmp);

	int iPlayerId = 1;

	while(iPlayerId <= N)

	{

		//如果已经服务过,则pass

		if(arrPlayers[iPlayerId].isServed)

		{

			iPlayerId++;

			continue;

		}

		else

		{

			int iFreeTabId = getAnFreeTab(K, arrPlayers[iPlayerId].iArrTime);

			if(arrTables[iFreeTabId].isVip) //VIP桌子空闲时,应该让等待队列中的VIP用户优先使用

			{

				//在当前时间的等待队列中找到一个VIP用户。

				int tmpId = getAnVipPlayer(iPlayerId, arrTables[iFreeTabId].iAvaiTime);

				if(tmpId == -1)//没有VIP用户,则把VIP桌子分配给当前用户

				{

					processAnCus(iFreeTabId, iPlayerId);

					iPlayerId++;

				}

				else //否则把桌子分配给VIP用户tmpId

				{

					processAnCus(iFreeTabId, tmpId);

				}

			}

			else //非VIP桌子空闲,则分配给当前用户

			{

				processAnCus(iFreeTabId, iPlayerId);

				iPlayerId++;

			}

			

		}

		

	}

}





//以正常的格式打印出时间信息

void printTimeInNormal(int iSec)

{

	int tmp = iSec;

	char strHour[][3] = {"08","09","10","11","12","13","14","15","16","17","18","19","20","21"};

	int sec = tmp%60;

	tmp /= 60;

	int min = tmp%60;

	int hour = tmp/60;

	if(min < 10)

	{

		cout<<strHour[hour]<<":0"<<min;

	}

	else

		cout<<strHour[hour]<<":"<<min;

	if(sec < 10)

		cout<<":0"<<sec;

	else

		cout<<":"<<sec;

	

}





void outputRes()

{

	sort(arrPlayers+1,arrPlayers+N+1,lessCmp2);

	int i,j,tmp;

	for(i=1; i<=N; i++)

		if(arrPlayers[i].isServed)

		{

			printTimeInNormal(arrPlayers[i].iArrTime);

			cout<<" ";

			printTimeInNormal(arrPlayers[i].iArrTime + arrPlayers[i].iWaitTime);

			if(arrPlayers[i].iWaitTime%60 >= 30)

				cout<<" "<<arrPlayers[i].iWaitTime/60 + 1<<endl;

			else

				cout<<" "<<arrPlayers[i].iWaitTime/60<<endl;

		}

	for(j=1; j<=K; j++)

	{

		if(j == 1)

			cout<<arrTables[j].iCount;

		else

			cout<<" "<<arrTables[j].iCount;

	}

	cout<<endl;

}





int main()

{

	inputData();

	process();

	outputRes();

	return 0;

}

  

你可能感兴趣的:(table)