| ||||||||||
| 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