PAT 1017. Queueing at Bank (25)
#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_WIN = 100+5;
const int OFF_TIME = 9*60*60;
const int ONE_HOUR = 60*60;
struct Customer
{
int iArrTime; //到达的时间
int iProTime; //处理的时间
int iWaitTime; //等待的时间
bool isServed;//是否被处理
};
Customer arrCus[MAX_N];
struct Windows
{
int iAvaiTime;//窗口available的时间
};
Windows arrWins[MAX_WIN];
//按到达时间进行排序
bool lessCmp(Customer cus1, Customer cus2)
{
return cus1.iArrTime < cus2.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 initData(int N,int K)
{
int i,j;
for(i=0; i<N; i++)
{
arrCus[i].iArrTime = 0;
arrCus[i].iProTime = 0;
arrCus[i].iWaitTime = 0;
arrCus[i].isServed = true;
}
for(j=0; j<K; j++)
{
arrWins[j].iAvaiTime = 0;
}
}
//得到一个空闲的窗口,遍历K个窗口,找到窗口available最早的时间
int getAnFreeWin(int K)
{
int iAvaTimeMin = arrWins[0].iAvaiTime;
int iWinIndex = 0;
for(int i=1; i<K; i++)
if(arrWins[i].iAvaiTime < iAvaTimeMin)
{
iAvaTimeMin = arrWins[i].iAvaiTime;
iWinIndex = i;
}
return iWinIndex;
}
int max(int a,int b)
{
return a>b?a:b;
}
//窗口iWinId处理完一个客户后,需要更新窗口available最早的时间
void updateWinsInfo(int iWinId,int iCusId)
{
int iCurTime = max(arrWins[iWinId].iAvaiTime,arrCus[iCusId].iArrTime);
if(arrCus[iCusId].iProTime <= ONE_HOUR)//处理的时间不能超过一个小时
arrWins[iWinId].iAvaiTime =iCurTime + arrCus[iCusId].iProTime;
else
arrWins[iWinId].iAvaiTime =iCurTime + ONE_HOUR;
}
//将iCusId客户放到窗口iWinId进行处理
void processAnCus(int iWinId, int iCusId)
{
//如果在客户到之前就有窗口空闲,或者在下班以后窗口才空闲,则等待时间为0
if(arrWins[iWinId].iAvaiTime == 0) //开始就空闲的窗口
{
if(arrCus[iCusId].iArrTime < 0)
arrCus[iCusId].iWaitTime = abs(arrCus[iCusId].iArrTime);
else if(arrCus[iCusId].iArrTime > OFF_TIME)
{
arrCus[iCusId].iWaitTime = 0;
arrCus[iCusId].isServed = false;
}
else //没有等待,直接到窗口。
arrCus[iCusId].iWaitTime = 0;
}
else//处理过客户的窗口
{
//if(arrWins[iWinId].iAvaiTime > OFF_TIME || arrCus[iCusId].iArrTime > OFF_TIME)//下班后的将不被处理
if(arrCus[iCusId].iArrTime > OFF_TIME)//之前一直有个case过不了,发现是题目意思理解错了。。
//即,客户只要在17:00之前到达银行,那么即使窗口的avaliable时间在17:00以后,那银行还是需要给
//客户进行服务的
{
arrCus[iCusId].iWaitTime = 0;
arrCus[iCusId].isServed = false;
}
else
{
if(arrWins[iWinId].iAvaiTime <= arrCus[iCusId].iArrTime)
arrCus[iCusId].iWaitTime = 0;
else
arrCus[iCusId].iWaitTime = arrWins[iWinId].iAvaiTime - arrCus[iCusId].iArrTime;
}
}
updateWinsInfo(iWinId,iCusId);
}
//获得所有客户的等待时间
double getAverageWaitTime(int N)
{
int iSum = 0;
int iCount = 0;
for(int i=0; i<N; i++)
if(arrCus[i].isServed)
{
iSum += arrCus[i].iWaitTime;
iCount++;
}
if(iCount == 0)
return 0;
else
return (double(iSum)/60)/iCount;
}
//对在等待队列上的客户进行处理
void process(int N, int K)
{
sort(arrCus,arrCus+N,lessCmp);
int iCusId = 0;
while(iCusId < N)
{
int iFreeWinId = getAnFreeWin(K);
processAnCus(iFreeWinId, iCusId);
iCusId++;
}
}
int main()
{
int N,K,i,j,iProTime;
char chArrTime[10];
scanf("%d %d",&N,&K);
initData(N,K);
for(i=0; i<N; i++)
{
scanf("%s",chArrTime);
int iRelTime = getRelTime(chArrTime);
arrCus[i].iArrTime = iRelTime;
scanf("%d",&iProTime);
arrCus[i].iProTime = iProTime*60;
}
process(N, K);
cout<<fixed<<setprecision(1)<<getAverageWaitTime(N)<<endl;
return 0;
}
多学习,多总结。

浙公网安备 33010602011771号