Poj Solution 1025

http://poj.org/problem?id=1025

#include <iostream>
class Room {
public:
int fNo , rNo; // rNo表示房间号,fNo表楼层号,其中fNo-2表楼外。rNo=-1表示电梯
char * toString()  
{    // 此函数线程不安全,不过用在此题没问题。千万不能在printf()这类函数内两次调用此函数。
   static char str_room[5];
   sprintf(str_room,"%02d%02d",fNo,rNo);
   return str_room;
}
Room& operator = ( const Room& room ) { fNo=room.fNo; rNo=room.rNo; return *this; }
};
class Time {
public:
char tstr[9];   // Time类自带了用于转换的 char[]。
int h , m , s ;
Time() { h=m=s=0; }
Time(int hh,int mm,int ss) { h=hh; m=mm; s=ss; }
void setTime(char * str)
{
   h = (str[0]-'0')*10 + (str[1]-'0') ;
   m = (str[3]-'0')*10 + (str[4]-'0') ;
   s = (str[6]-'0')*10 + (str[7]-'0') ;
}
char* toString() { sprintf(tstr,"%02d:%02d:%02d",h,m,s); return tstr; }
bool operator == (const Time& t){ return ( h==t.h && m==t.m && s==t.s ); }
Time& operator = (const Time& t){ h=t.h; m=t.m; s=t.s; return *this; }
bool operator < (const Time& t)
{ 
   if(h!=t.h) return h<t.h;
   if(m!=t.m) return m<t.m;
   if(s!=t.s) return s<t.s;
   return false;
}
Time& add(int n)
{
   int temp;
   if( n>=3600 )
   { temp = n/3600; h += temp; n -= temp*3600; }
   if( n>=60 )
   { 
    temp = n/60 ; m += temp; n -= temp*60 ;
    if(m>=60) { m-=60; ++h; }
   }
   if( n<60 ) s += n ;
   if( s>=60) { s-=60; ++m; }
   return *this;
}
};
class Agent {
public:
char code;
Time startWait , nextTime ;
Room roomList[100];   // 最多访问 100 个房间
int lastTime[100] , totalRoom;
char actionList[100][60];   // 假设最多有100个action
int actNum , nextRoom , waitFlag;
Room pos ;
Agent* next;
Agent(char c,char* str)
{ 
   code=c; 
   waitFlag = actNum = nextRoom = 0; 
   next=NULL; 
   nextTime.setTime(str); 
   pos.fNo=-2; 
}
void doAct();     // 此函负责执行一个步骤
void moveTo(Room room);   // 负责Agent的移动和访问room。包括乘电梯操作。
};
class AgentList {
public:
Agent* head ;
AgentList() { head=NULL; }
void add(Agent* ag)
{
   Agent *par , *cur;
   par = cur = head;
   while( cur!=NULL && cur->code < ag->code )
   { par=cur; cur=cur->next; }
   if(cur==head){ head=ag; ag->next=cur; return; }
   par->next = ag;
   ag->next = cur ;
}
void del(Agent *ag) // 只是取下节点,并未删除,这里会内存泄露!不过不想管了。
{
   if(ag==head) { head=head->next; ag->next=NULL; return; } 
   Agent *par , *cur;
   par = cur = head;
   while( cur!=NULL && cur!=ag ) { par=cur; cur=cur->next; }
   par->next = ag->next ;
   ag->next = NULL;
}
};
/* ------------------------- 数据结构定义完毕 ----------------------------------- */

/***************************************************************************************/

Time roomTable[10][10] , elevator[10] , nowTime;
AgentList aglist , result ;

void Agent::moveTo( Room room )   // 此函数用于单步执行,包括访问房间和电梯两大块
{
//------------------------------ 以下是进电梯相关操作 ----------------------
if( pos.rNo!=-1 && room.rNo==-1 ) 
{
   waitFlag = 0;
   nextTime.add(10) ;
   sprintf(actionList[actNum++],
    "%s %s Transfer from room %s to elevatorn",
    nowTime.toString(),nextTime.toString(),pos.toString() );
   pos.rNo = -1; // 进入电梯或电梯等待队列
   return ;
}
if( room.rNo==-1 ) // 如果需要进电梯
{
   if( nowTime.s%5!=0 ) {   // 时间不是 5s 倍数,则等待。
    startWait = nowTime; 
    waitFlag=1;   // 等待标识 waitFlag=1
    nextTime.add( 5 - nextTime.s%5 );
    sprintf(actionList[actNum++],
     "%s %s Waiting in elevator queuen", startWait.toString(), nextTime.toString() );
    pos.rNo = -1;
    return;
   } 
   else 
   {
    if( nowTime < elevator[pos.fNo] )   // 如果优先级不高(电梯已有人),等待。
    {
     if( waitFlag==0 ){ startWait = nowTime; waitFlag=1; }
     else --actNum;
     nextTime.add( 5 );
     sprintf(actionList[actNum++],
      "%s %s Waiting in elevator queuen",startWait.toString(), nextTime.toString() );
     pos.rNo = -1;
     return;
    } 
    else 
    {    // 乘电梯中
     int et = (room.fNo-pos.fNo)*30 ;
     et = ( et<0?(-et):et ) ;
     nextTime.add( et );
     sprintf(actionList[actNum++], "%s %s Stay in elevatorn", nowTime.toString() , nextTime.toString() );
     elevator[pos.fNo] = nowTime.add( 5 ); // 电梯时间加 5
     pos.fNo = room.fNo;   // 楼层更新
     waitFlag = 0 ;
     return;
    }
   }
} 
//----------------------- 以下是 出电梯 ---------------
if( pos.rNo==-1 && room.rNo!=-1 )
{
   waitFlag = 0;
   nextTime.add(10);
   sprintf(actionList[actNum++],
    "%s %s Transfer from elevator to room %sn",
    nowTime.toString() , nextTime.toString() , room.toString());
   pos.rNo = room.rNo ;
   return ;
}
//----------------------- 以下是 同层房间访问 相关操作 -----------------------------
if( pos.rNo!=room.rNo )  
{       // 不同房间,则花 10s 换房间
   waitFlag = 0;
   nextTime.add(10);
   char temp[5];
   strcpy(temp,room.toString());
   sprintf(actionList[actNum++],
    "%s %s Transfer from room %s to room %sn",
    nowTime.toString(), nextTime.toString(), pos.toString(), temp );
   pos.rNo = room.rNo ;
   return ;
}
if( nowTime < roomTable[room.fNo][room.rNo] )   // 进入等待队列
{
   nextTime = roomTable[room.fNo][room.rNo] ;
   if( waitFlag==0 ) { startWait=nowTime; waitFlag=1; }
   else --actNum;
   sprintf(actionList[actNum++],
    "%s %s Waiting in front of room %sn",
    startWait.toString(), nextTime.toString(), room.toString() );
   pos.rNo = room.rNo;
   return ;
}
waitFlag = 0; // 等待标识 清除
nextTime.add( lastTime[nextRoom++] ); // 进入房间,
roomTable[room.fNo][room.rNo] = nextTime;   // 更新房间信息
sprintf(actionList[actNum++],
   "%s %s Stay in room %sn",
   nowTime.toString(),nextTime.toString(),room.toString() );
pos.rNo = room.rNo;
return;
//-------------------------------------------------------
}
void Agent::doAct()   // 执行函数,只执行一步(下面分为 进楼,访问,出楼 三种情况考虑 )
{
Room roomTo;
//----------------- 以下处理出楼 -----------------------
if( nextRoom==totalRoom )
{
   if( pos.fNo==1 )
   {
    nextTime.add(30);
    sprintf(actionList[actNum++],"%s %s Exitn",nowTime.toString() , nextTime.toString() );
    aglist.del( this );   // 从待处理链表 删除此 Agent
    result.add( this );   // 加入结果集。
    return ;
   }
   if( pos.rNo==-1 )
   {
    roomTo.fNo=1; roomTo.rNo=-1;
    moveTo( roomTo );
    return;
   }
   roomTo.fNo = pos.fNo;
   roomTo.rNo = -1;
   moveTo( roomTo );
   return;
}
//----------------- 以下处理进楼 -----------------------
roomTo = roomList[nextRoom];
if( pos.fNo==-2 ) // 进楼
{ 
   nextTime.add(30);
   sprintf(actionList[actNum++],"%s %s Entryn",nowTime.toString() , nextTime.toString() );
   pos.fNo = 1; pos.rNo=-2; // rNo=-2 表示刚进楼,在门口。
   return ;
}
if( pos.rNo==-2 ) // 刚进楼,准备访问。
{
   if( roomTo.fNo==1 )   // 访问目标在一楼
   { 
    pos.rNo = roomTo.rNo ;
    moveTo( roomList[nextRoom] );
   } else {
    pos.rNo = -1 ;
    roomTo.rNo = -1;
    moveTo( roomTo ); // 不在一楼,准备进入电梯
   }
   return ;
}
//---------------- 以下处理 楼内访问 ----------------------
if( pos.fNo!=roomTo.fNo )
{
   roomTo.rNo=-1;
   moveTo( roomTo );
}
else
   moveTo( roomTo );
}

void Execute()   // 总调函数,每次选一个触发时间且编号靠前的Agent 执行一步。
{
Agent *p,*cur ;
while( aglist.head!=NULL )
{
   nowTime.setTime("24:60:60"); // nowTime 设为最大值
   p = cur = aglist.head;
   while(cur!=NULL)
   {
    if( cur->nextTime < nowTime ) { nowTime=cur->nextTime; p=cur; }
    cur = cur->next ;
   }
   p->doAct();   // 被选上的 Agent 执行一步。
}
}
int main()
{
char cd , str_t[10];
while( scanf("%c ",&cd) && cd!='.' )
{
   scanf("%s",str_t);
   Agent *ag = new Agent(cd,str_t);
   aglist.add(ag);
   int roomNo , lastTime , i=0;
   while( scanf("%dn",&roomNo) && roomNo )
   {
    scanf("%d",&lastTime);
    ag->roomList[i].fNo = roomNo/100;
    ag->roomList[i].rNo = roomNo%100;
    ag->lastTime[i] = lastTime;
    ++i;
   }
   ag->totalRoom = i;   // 每个 Agent 所需访问的房间总数
}
Execute(); // 执行调度
Agent *ag = result.head;
while( ag!=NULL )
{
   printf("%cn",ag->code);
   for( int i=0; i<ag->actNum ; ++i )
    printf("%s",ag->actionList[i]);
   printf("n");
   ag = ag->next;
}
return 0;
}
											
This entry was posted in poj. Bookmark the permalink.