Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

Re:此题关键点说明(附代码)

Posted by SDRJ102010010367 at 2012-04-25 15:43:33 on Problem 1025
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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator