| ||||||||||
| 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:Re:此题关键点说明(附代码) Posted by:ixor at 2011-03-20 15:39:25 > 这个解法谈不上简洁,它只是正确解决了问题,可以用来验证别的解法。用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