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; }
多学习,多总结。