Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
Re:此题关键点说明(附代码)In Reply To:此题关键点说明(附个人思路) Posted by:ixor at 2011-03-20 15:35:51 这个解法谈不上简洁,它只是正确解决了问题,可以用来验证别的解法。用c++只不过是为了 理清思路,用c去实现应该会更精炼(但也许更抽象)。 //g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3 //written by ixor (linuxboy_007@hotmail.com) #include <vector> #include <map> #include <queue> #include <cstdlib> #include <cstdio> #include <iostream> #include <cassert> #include <cstring> using namespace std; #define ELEVATOR_ID( resID ) ( ( GET_FLOOR ( resID ) )*100 + 11 ) #define IS_ELEVATOR( resID ) ( ( resID ) % 100 == 11 ) #define IS_ROOM( resID ) ( ( resID ) != RECEPTION_ID && !IS_ELEVATOR( resID ) ) #define RECEPTION_ID 0 #define SAME_FLOOR( resID1, resID2 ) ( (resID1) / 100 == (resID2) / 100 ) #define GET_FLOOR( resID ) ( ( resID ) == RECEPTION_ID ? 1 : ( resID ) / 100 ) int timeInSec(const char *timeStr) { int hour, min, sec; sscanf(timeStr, "%d:%d:%d", &hour, &min, &sec); return hour * 3600 + min * 60 + sec; } void formatTime(char *buff, int time) { int hour, min, sec; hour = time / 3600; min = (time % 3600) / 60; sec = time % 60; sprintf(buff, "%02d:%02d:%02d", hour, min, sec); } typedef struct VisitEntry_TAG { int resID; int usingTime; } VisitEntry; class ResDescriptor; class ResMgr; class Agent { public: Agent(char pri, const char *timeStr); ~Agent() { while (!descriptionList.empty()) { delete descriptionList.back(); descriptionList.pop_back(); } } int tick(int time); void printLog( void ){ DescriptionList::const_iterator iter; printf( "%c\n", getPriority() ); for( iter = descriptionList.begin(); iter != descriptionList.end(); iter ++ ){ printf( "%s\n", *iter ); } } void addVisitEntry(VisitEntry & entry) { visitList.push(entry); } bool isFinished() const { return finished; } char getPriority() const { return priority; } private: void onGetResource(ResDescriptor * res, int tick); void onWaitResource(ResDescriptor * res, int tick); void onLoseResource(ResDescriptor * res, int tick); typedef enum AgentState_TAG { PENDING, WAITING, HOLDING, } AgentState; typedef queue < VisitEntry > VisitList; typedef vector< char * > DescriptionList; void addDescription(const char *buff) { int len = strlen(buff) + 1; char *des = new char[len]; strcpy(des, buff); descriptionList.push_back(des); } const VisitEntry & getCurEntry(void) const { assert( !visitList.empty() ); return visitList.front(); } void formatTimeSection(int start, int end) { prepareBuff(); formatTime(word, start); strcat(line, word); strcat(line, " "); formatTime(word, end); strcat(line, word); strcat(line, " "); } void popCurEntry(void) { assert(visitList.size()); visitList.pop(); } void prepareBuff(void) { line[0] = '\0'; word[0] = '\0'; tmpBuff[0] = '\0'; } bool finished; ResDescriptor *curRes; ResDescriptor *goalRes; char state; char priority; static char line[40]; static char word[10]; static char tmpBuff[40]; static ResMgr *resMgr; int wakeUpTime; int waitBeginTime; VisitList visitList; DescriptionList descriptionList; }; class ResDescriptor { public: ResDescriptor(int id): waitingQue(NULL), beginTime(0), usingTime(0), resID(id) {} ~ResDescriptor() { if (waitingQue) delete waitingQue; } virtual char acquire(Agent * agent, int usingTime_a, int tick) { if( queueEmpty() ){ if( !beginTime ) return giveRes( agent, usingTime_a, tick ); if( beginTime + usingTime <= tick ) return giveRes( agent, usingTime_a, tick ); return enque(agent); } return decideByQuePriority( agent, usingTime_a, tick ); } int getFloor(void) { return resID / 100; } int getBeginTime(void) { return beginTime; } int getUsingTime(void) { return usingTime; } int getID(void) { return resID; } typedef enum ResState_TAG { FREE, QUEUING } ResState; protected: typedef vector < Agent * >AgentQueue; char giveRes( Agent * agent, int usingTime_a, int tick ){ beginTime = tick; usingTime = usingTime_a; return FREE; } char decideByQuePriority( Agent * agent, int usingTime_a, int tick ){ assert( !queueEmpty() ); Agent *first = waitingQue->front(); if( first->getPriority() >= agent->getPriority() ){ if( !beginTime ){ if( first->getPriority() == agent->getPriority() ) deque(); return giveRes( agent, usingTime_a, tick ); } if( beginTime + usingTime <= tick ){ if( first->getPriority() == agent->getPriority() ) deque(); return giveRes( agent, usingTime_a, tick ); } } return enque(agent); } char enque(Agent * agent) { if (!waitingQue) waitingQue = new AgentQueue(); AgentQueue::iterator iter; for (iter = waitingQue->begin(); iter != waitingQue->end(); iter++) { if ((*iter)->getPriority() >= agent->getPriority()) break; } if ( !waitingQue->empty() && iter != waitingQue->end() && (*iter)->getPriority() == agent->getPriority() ) return QUEUING; waitingQue->insert(iter, agent); return QUEUING; } void deque() { if (waitingQue->size()) waitingQue->erase( waitingQue->begin() ); else assert(false); } bool queueEmpty() { if (!waitingQue) return true; return waitingQue->empty(); } AgentQueue *waitingQue; int resID; int beginTime; int usingTime; }; class RoomDescriptor: public ResDescriptor{ public: RoomDescriptor( int id ):ResDescriptor( id ){ assert( IS_ROOM( id ) ); } }; class ReceptionDescriptor: public ResDescriptor{ public: ReceptionDescriptor( int id ):ResDescriptor( id ){ assert( id == RECEPTION_ID ); } char acquire(Agent * agent, int usingTime_a, int tick){ return FREE; } }; class ElevatorDescriptor:public ResDescriptor{ public: ElevatorDescriptor( int id ):ResDescriptor( id ){ assert( IS_ELEVATOR( id ) ); } char acquire(Agent * agent, int usingTime_a, int tick){ if( tick % 5 ) return enque( agent ); return ResDescriptor::acquire( agent, 5, tick ); } }; class ResMgr { public: typedef map < int, ResDescriptor * >ResRecord; static ResMgr *instance() { if (!s_instance) s_instance = new ResMgr(); return s_instance; } ResDescriptor *getRes(int resID) { if (resRec.find(resID) == resRec.end()){ if( IS_ELEVATOR( resID ) ) resRec[resID] = new ElevatorDescriptor( resID ); else if( resID == RECEPTION_ID ) resRec[resID] = new ReceptionDescriptor( resID ); else resRec[resID] = new RoomDescriptor(resID); } return resRec[resID]; } ~ResMgr() { ResRecord::iterator iter; for (iter = resRec.begin(); iter != resRec.end(); iter++) { delete iter->second; } } private: ResMgr() { } ResRecord resRec; static ResMgr *s_instance; }; ResMgr *ResMgr::s_instance = NULL; class AgentMgr { public: static AgentMgr *instance() { if (!s_instance) s_instance = new AgentMgr(); return s_instance; } bool isFinished(void)const { AgentAry::const_iterator iter; for (iter = agents.begin(); iter != agents.end(); iter++) { if (!(*iter)->isFinished()) return false; } return true; } void addAgent(Agent * agent) { AgentAry::iterator iter; for (iter = agents.begin(); iter != agents.end(); iter++) { if ((*iter)->getPriority() > agent->getPriority()) break; } agents.insert(iter, agent); } Agent *getAgent(int idx) const { assert(idx >= 0 && idx < getAgentNum()); return agents[idx]; } int getAgentNum() const { return agents.size(); } private: typedef vector < Agent * >AgentAry; static AgentMgr *s_instance; AgentAry agents; }; AgentMgr *AgentMgr::s_instance = NULL; Agent::Agent(char pri, const char *timeStr):finished(false), priority(pri), curRes(NULL), goalRes(NULL), state(PENDING), waitBeginTime(0) { wakeUpTime = timeInSec(timeStr); goalRes = resMgr->getRes(RECEPTION_ID); } int Agent::tick(int time) { if (time != wakeUpTime) return wakeUpTime; if (curRes && state == HOLDING) { onLoseResource(curRes, time); curRes = NULL; return wakeUpTime; } int resState; if (goalRes->getID() == RECEPTION_ID) resState = goalRes->acquire(this, 0, time); else if( IS_ELEVATOR( goalRes->getID() ) ) resState = goalRes->acquire(this, 0, time); else resState = goalRes->acquire(this, getCurEntry().usingTime, time); switch (resState) { case ResDescriptor::FREE: if (state == WAITING) { formatTimeSection(waitBeginTime, time); if (IS_ELEVATOR(goalRes->getID())) sprintf(tmpBuff, "Waiting in elevator queue"); else sprintf(tmpBuff, "Waiting in front of room %04d", goalRes->getID()); strcat(line, tmpBuff); addDescription(line); waitBeginTime = 0; } onGetResource(goalRes, time); state = HOLDING; break; case ResDescriptor::QUEUING: if (state != WAITING) { waitBeginTime = time; state = WAITING; } onWaitResource(goalRes, time); break; default: assert(false); break; } return wakeUpTime; } void Agent::onGetResource(ResDescriptor * res, int tick) { if (res->getID() == RECEPTION_ID) { formatTimeSection(tick, tick + 30); strcat(line, "Entry"); addDescription(line); wakeUpTime += 30; } else { if( IS_ELEVATOR( res->getID() ) ){ int stayTime; if( visitList.empty() ){ stayTime = ( GET_FLOOR( goalRes->getID() ) - 1 ) * 30; assert( stayTime > 0 ); } else { stayTime = abs( GET_FLOOR( goalRes->getID() ) - GET_FLOOR( getCurEntry().resID ) ) * 30; } formatTimeSection(tick, tick + stayTime ); sprintf(tmpBuff, "Stay in elevator"); wakeUpTime += stayTime; }else{ formatTimeSection(tick, tick + getCurEntry().usingTime); sprintf(tmpBuff, "Stay in room %04d", res->getID()); wakeUpTime += getCurEntry().usingTime; } strcat(line, tmpBuff); addDescription(line); } curRes = res; } void Agent::onWaitResource(ResDescriptor * res, int tick) { if( IS_ELEVATOR( res->getID() ) ){ wakeUpTime = tick + 5 - tick % 5; return; } wakeUpTime = res->getBeginTime() + res->getUsingTime(); assert( wakeUpTime > tick ); } void Agent::onLoseResource(ResDescriptor * res, int tick) { if (res->getID() == RECEPTION_ID) { if (GET_FLOOR(getCurEntry().resID) == 1) goalRes = resMgr->getRes(getCurEntry().resID); else goalRes = resMgr->getRes(ELEVATOR_ID(RECEPTION_ID)); return; } if( IS_ELEVATOR( res->getID() ) ){ if( visitList.empty() ) goto EXIT; formatTimeSection(tick, tick + 10); sprintf( tmpBuff, "Transfer from elevator to room %04d", getCurEntry().resID ); strcat( line, tmpBuff ); addDescription( line ); goalRes = resMgr->getRes( getCurEntry().resID ); wakeUpTime += 10; }else{ popCurEntry(); if( visitList.empty() ){ if( GET_FLOOR( curRes->getID() ) == 1 ){ EXIT: formatTimeSection( tick, tick + 30 ); strcat( line, "Exit" ); addDescription( line ); finished = true; return; } formatTimeSection( tick, tick + 10 ); sprintf( tmpBuff, "Transfer from room %04d to elevator", curRes->getID() ); strcat( line, tmpBuff ); addDescription( line ); goalRes = resMgr->getRes( ELEVATOR_ID( curRes->getID() ) ); wakeUpTime += 10; return; } formatTimeSection(tick, tick + 10); if (SAME_FLOOR(getCurEntry().resID, curRes->getID())) { sprintf(tmpBuff, "Transfer from room %04d to room %04d", curRes->getID(), getCurEntry().resID); strcat(line, tmpBuff); addDescription(line); goalRes = resMgr->getRes(getCurEntry().resID); wakeUpTime += 10; } else { sprintf(tmpBuff, "Transfer from room %04d to elevator", curRes->getID()); strcat(line, tmpBuff); addDescription(line); goalRes = resMgr->getRes(ELEVATOR_ID(curRes->getID())); wakeUpTime += 10; } } } ResMgr *Agent::resMgr = ResMgr::instance(); char Agent::line[] = { '\0' }; char Agent::tmpBuff[] = { '\0' }; char Agent::word[] = { '\0' }; void action(int startTime) { int t, idx; int nearestWakeUp = -1; int wakeUp; AgentMgr *agentMgr = AgentMgr::instance(); Agent *agent; for (t = startTime; !agentMgr->isFinished(); t = nearestWakeUp) { nearestWakeUp = -1; for (idx = 0; idx < agentMgr->getAgentNum(); idx++) { agent = agentMgr->getAgent(idx); if( agent->isFinished() ) continue; wakeUp = agent->tick(t); if( nearestWakeUp == -1 || wakeUp < nearestWakeUp ) nearestWakeUp = wakeUp; //printf("tick:%d\n", t); //agent->printLog(); } } for( idx = 0; idx < agentMgr->getAgentNum(); idx ++ ){ agent = agentMgr->getAgent( idx ); agent->printLog(); printf("\n"); } } int main(void) { int n; char buff[15]; Agent *curAgent; int resourceID; int time; int startTime = -1; char priority; VisitEntry entry; AgentMgr *agentMgr = AgentMgr::instance(); //FILE *stdin; //stdin = fopen( "data.txt", "r" ); while (true) { fscanf( stdin, "%[^\n]", buff ); while ( fgetc( stdin ) != '\n') ; if (strlen(buff) == 1 && buff[0] == '.') break; curAgent = new Agent(buff[0], &buff[2]); if( startTime == -1 || timeInSec( &buff[2] ) < startTime ) startTime = timeInSec( &buff[2] ); agentMgr->addAgent(curAgent); while (true) { fscanf( stdin, "%[^\n]", buff ); while ( fgetc( stdin ) != '\n' ); if (strlen(buff) == 1 && buff[0] == '0') break; sscanf(buff, "%d %d", &resourceID, &time); entry.resID = resourceID; entry.usingTime = time; curAgent->addVisitEntry(entry); } } //fclose(stdin); action( startTime ); return 0; } Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator