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

      

    多学习,多总结。
  • 相关阅读:
    Linux之uboot分析与移植20160601
    华为C语言编程规范
    中兴软件编程规范C/C++
    枚举esum20160530
    GPS之NMEA协议20160526
    uC/OS-II之系统函数20160526
    UART,USART,SPI,I2C等总线的介绍与区别20160526
    JAVA中使用JSON进行数据传递
    Android:单元测试Junit的配置
    IntentService简介
  • 原文地址:https://www.cnblogs.com/yanhaiming/p/2818280.html
Copyright © 2020-2023  润新知