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

  

posted @ 2012-12-14 16:31  Frank@609  Views(1284)  Comments(0Edit  收藏  举报