#include<stdio.h>
#include<malloc.h>
typedef enum {paClosed=0, paLand=1,paTakeoff=2,paLandTakeoff=3}PLANEACTION;
const char* const PlaneActionLabels[]={"","A","D","AD"};
typedef struct _tagPort* P_PORT;
typedef struct _tagPlane* P_PLANE;
typedef struct _tagPlane
{
int no; /*공항의 각 활주로에서 부여한 비행기 번호*/
int time_arrive; /*공항 상공 도착 시각*/
int time_can_wait_from_arrive; /*도착부터 이 시간 안에 착륙해야 함(연료문제)*/
int time_to_land_from_arrive; /*도착부터 이 시간은 지나야 착륙할 수 있을 것으로 예정됨*/
PLANEACTION action; /*착륙 또는 이륙*/
P_PORT port; /*해당 비행기가 이착륙할 활주로*/
int prev_port_no; /*비상 착륙을 위해 비상착륙 활주로로 이동 시 원래 활주로 번호*/
P_PLANE next; /*대기중인 다음 비행기*/
}PLANE;
#define MAX_PLANE_COUNT_PER_PORT 3
typedef struct _tagPort
{
P_PLANE head[2],tail[2]; /*선회(대기) 중인 첫비행기와 마지막 비행기: 착륙과 이륙을 구분*/
int no;
int max_plane_count; /*이 활주로를 이용하기 위해 선회(대기)할 수 있는 최대 비행기수*/
int counts[2]; /*현재 선회(대기) 중인 비행기 수*/
int current_plane_noes[2]; /*착륙(이륙)할 비행기에 부여할 번호*/
int time_wait_to_land; /*도착부터 착륙까지 선회(대기)해야 할 시간*/
int accu_time_waits[2];/*모든 비행기의 대기시간 합*/
int accu_counts[2]; /*이 큐를 거쳐간 비행기 수*/
PLANEACTION usage;/*활주로의 용도*/
PLANEACTION action_to_take; /*착륙 또는 이륙*/
int time_to_land_from_arrive; /*공항 상공 도착후 착륙까지 각 비행기가 대기해야 할 시간*/
int plane_count_goto_another_port;
int plane_count_from_another_port;
}PORT;
#define PORT_COUNT 3
typedef struct _tagAirport
{
P_PORT ports; /*활주로*/
int port_count; /*활주로 수*/
int reserved_port_no;/*특정 용도로만 사용할 수 있는 활주로 번호*/
PLANEACTION reserved_for_what;/*위 활주로의 용도*/
int time_to_land_from_arrive; /*공항 상공 도착후 착륙까지 각 비행기가 대기해야 할 시간*/
int time_interval_each_plane_can_act;
int plane_count_of_cant_service;
}AIRPORT, *P_AIRPORT;
P_PLANE AddToPort(P_PORT pport,PLANEACTION action,int time_arrive,int time_limit_to_land_from_arrive);
P_PLANE AddToPortHead(P_PORT pport,P_PLANE plane,int time_arrive);
P_PLANE AddToPortTail(P_PORT pport,P_PLANE plane,int time_arrive);
P_PLANE RemoveFromPort(P_PORT pport,PLANEACTION action,int current_time);
int HasThisPlane(P_PORT pport,P_PLANE plane);
P_PLANE SearchPrevPlane(P_PORT pport,P_PLANE plane);
P_PLANE RemoveThisPlaneFromPort(P_PORT pport,P_PLANE plane,int current_time);
void ResetPort(P_PORT pport);
void CreatePorts(P_AIRPORT pairport,int max_plane_count,int reserved_port_no,PLANEACTION reserved_for_what);
void ResetPorts(P_AIRPORT pairport);
void PrintPortStatus(P_PORT pport,int current_time);
void PrintAirportStatus(P_AIRPORT pairport,int current_time);
void ControlAirport(P_AIRPORT pairport);
int GetPort(P_AIRPORT pairport, PLANEACTION action,int port_interested);
void ControlEmergency(P_AIRPORT pairport,int current_timeo);
int CanServiceThisPlaneFirst(P_PORT pport,P_PLANE plane,int current_time);
int CanAccomidate(P_PORT pport,PLANEACTION action);
int IsEmergent(P_PLANE plane,int current_time);
int MoveEmgegentPlane(P_AIRPORT pairport,P_PLANE plane,int current_time);
void TakeAction(P_AIRPORT pairport,int current_time);
void ReceivePlanes(P_AIRPORT pairport,PLANEACTION action
,int current_time,int time_can_wait,int interested_port_no);
FILE *g_FP_LOG;
#define SAVE_LOG_TO_FILE
int main()
{
char temp;
AIRPORT airport;
airport.port_count = PORT_COUNT;
airport.reserved_port_no = 1;
airport.reserved_for_what = paTakeoff;
airport.time_to_land_from_arrive = 25;
CreatePorts(&airport,MAX_PLANE_COUNT_PER_PORT,1,paTakeoff);
#ifdef SAVE_LOG_TO_FILE
g_FP_LOG = fopen("Log.txt","wt");
#else
g_FP_LOG = stdout;
#endif
ControlAirport(&airport);
ResetPorts(&airport);
#ifdef SAVE_LOG_TO_FILE
fclose(g_FP_LOG);
fprintf(stdout,"Log is saved to file, \"Log.txt\".");
#endif
scanf("%c",&temp);
return 0;
}
void ControlAirport(P_AIRPORT pairport)
{
int current_time;
/*pairport->time_to_land_from_arrive = 25;*/
int report_time_interval=200;
int time_interval_each_plane_arrive=15;
int time_interval_each_plane_can_take_action=10;
int time_can_wait=20;
int port_to_service=0;
int i,j,idx;
AddToPort(&pairport->ports[0],paLand,0,21);
AddToPort(&pairport->ports[0],paLand,0,21);
AddToPort(&pairport->ports[2],paLand,0,21);
AddToPort(&pairport->ports[2],paLand,0,21);
pairport->time_interval_each_plane_can_act = 5;
for(current_time=1 ;current_time<1000 ;current_time=current_time+1){
if(current_time%time_interval_each_plane_can_take_action==0){
TakeAction(pairport,current_time);
}
ControlEmergency(pairport,current_time);
if(current_time%time_interval_each_plane_arrive==0){
for(j=0 ;j<2 ;j=j+1){
ReceivePlanes(pairport,j+1,current_time,time_can_wait,port_to_service);
}
port_to_service = (port_to_service + 1) % pairport->port_count;
}
if(current_time%report_time_interval==0){
PrintAirportStatus(pairport,current_time);
}
}/*end of for(i*/
PrintAirportStatus(pairport,current_time);
}
void TakeAction(P_AIRPORT pairport,int current_time)
{
int i;
P_PLANE plane;
PLANEACTION action;
for(i=0 ;i<pairport->port_count ;i=i+1){
action = pairport->ports[i].action_to_take;
plane = pairport->ports[i].head[action-1];
if(plane!=NULL && current_time-plane->time_arrive>=plane->time_to_land_from_arrive){
fprintf(g_FP_LOG,"\\n%s: Plane%d in Port%d(%d) at %d",(action==paLand?"Land":"Takeoff")
,plane->no,plane->port->no,plane->prev_port_no,current_time);
plane=RemoveFromPort(&pairport->ports[i],action,current_time);
if(plane!=NULL) free(plane);
}
if(action==paLand) pairport->ports[i].action_to_take=paTakeoff;
else pairport->ports[i].action_to_take=paLand;
}
}
void ReceivePlanes(P_AIRPORT pairport,PLANEACTION action_to_take
,int current_time,int time_can_wait,int interested_port_no)
{
int i,idx,port_no;
for(i=interested_port_no ;i<pairport->port_count+interested_port_no ;i=i+1){
port_no = i%pairport->port_count;
idx = GetPort(pairport,action_to_take,port_no);
if(CanAccomidate(&pairport->ports[idx],action_to_take)!=0){
AddToPort(&pairport->ports[idx],action_to_take,current_time,time_can_wait);
fprintf(g_FP_LOG,"\\nenqueue: time:%d action:%s int_port:%d",current_time,(action_to_take==paLand?"Land":"Takeoff"),interested_port_no);
}else{
fprintf(g_FP_LOG,"\\nCan\'t enqueue: time:%d action:%s int_port:%d %d",current_time,(action_to_take==paLand?"Land":"Takeoff"),interested_port_no,pairport->plane_count_of_cant_service);
pairport->plane_count_of_cant_service = pairport->plane_count_of_cant_service + 1;
}
}/*end of for(i*/
}
int GetPort(P_AIRPORT pairport, PLANEACTION action,int port_interested)
{
int i,minidx,port_no;
port_interested = port_interested%pairport->port_count;
if((port_interested!=pairport->reserved_port_no || (action&pairport->reserved_for_what)!=0)
&& CanAccomidate(&pairport->ports[port_interested],action) ) return port_interested;
minidx = port_interested;
for(i=port_interested+1 ;i<pairport->port_count+port_interested-1 ;i=i+1){
port_no = i%pairport->port_count;
if(CanAccomidate(&pairport->ports[port_no],action)
&& pairport->ports[port_no].counts[action-1] < pairport->ports[minidx].counts[action-1]){
minidx = port_no;
}
}
return minidx;
}
void ControlEmergency(P_AIRPORT pairport,int current_time)
{
P_PLANE cur,plane;
int i;
for(i=0 ;i<pairport->port_count ;i=i+1){
if(i==pairport->reserved_port_no) continue;
plane = pairport->ports[i].head[0];
/*각 활주로의 선두에 있는 비행기는 그대로 기다렸다 착륙/이륙*/
if(plane!=NULL) plane = plane->next;
while(plane){
if(IsEmergent(plane,current_time)!=0){
cur = plane->next;
fprintf(g_FP_LOG,"\\nEmergent Plane:%d[%s] in port%d at %d",plane->no,PlaneActionLabels[plane->action],i,current_time);
if(MoveEmgegentPlane(pairport,plane,current_time)!=0){
fprintf(g_FP_LOG," => Move to port%d",plane->port->no);
}else{
fprintf(g_FP_LOG," => Can\'t move to another port");
}
plane = cur;
}else{
plane = plane->next;
}
}/*end of while(plane)*/
}/*end of for(i*/
}
int MoveEmgegentPlane(P_AIRPORT pairport,P_PLANE plane,int current_time)
{
int i;
if(pairport->reserved_port_no>=0
&& pairport->ports[pairport->reserved_port_no].counts[plane->action-1]
< pairport->ports[pairport->reserved_port_no].max_plane_count
/* && CanServiceThisPlaneFirst(&pairport->ports[pairport->reserved_port_no],plane,current_time)!=0*/){
RemoveThisPlaneFromPort(plane->port,plane,current_time);
AddToPortTail(&pairport->ports[pairport->reserved_port_no],plane,current_time);
return 1;
}
for(i=0 ;i<pairport->port_count ;i=i+1){
if(&pairport->ports[i]==plane->port) continue;
if(CanServiceThisPlaneFirst(&pairport->ports[i],plane,current_time)!=0){
RemoveThisPlaneFromPort(plane->port,plane,current_time);
AddToPortHead(&pairport->ports[i],plane,current_time);
return 1;
}
}
return 0;
}
int IsEmergent(P_PLANE plane,int current_time)
{
int wait_time,time_to_emergency;
wait_time = current_time - plane->time_arrive;
time_to_emergency = plane->time_can_wait_from_arrive - wait_time;
return (time_to_emergency<=0?1:0);
}
int CanServiceThisPlaneFirst(P_PORT pport,P_PLANE plane,int current_time)
{
if(pport->counts[plane->action-1]>=pport->max_plane_count || 0==(pport->usage&plane->action)) return 0;
if(pport->head[plane->action-1]!=NULL){
if(IsEmergent(pport->head[plane->action-1],current_time)!=0) return 0;
}
return 1;
}
int CanAccomidate(P_PORT pport,PLANEACTION action)
{
if(pport->counts[action-1]>=pport->max_plane_count || 0==(pport->usage&action)) return 0;
return 1;
}
P_PLANE AddToPort(P_PORT pport,PLANEACTION action,int time_arrive,int time_can_wait_from_arrive)
{
P_PLANE new_plane;
if(CanAccomidate(pport,action)==0) return NULL;
new_plane = (P_PLANE)malloc(sizeof(PLANE));
new_plane->next = NULL;
new_plane->no = pport->current_plane_noes[action-1];
new_plane->time_arrive = time_arrive;
new_plane->time_can_wait_from_arrive = time_can_wait_from_arrive;
new_plane->time_to_land_from_arrive = pport->time_to_land_from_arrive;
new_plane->action = action;
new_plane->prev_port_no = pport->no;
new_plane->port = pport;
if(NULL==pport->head[action-1]){
pport->head[action-1] = new_plane;
pport->tail[action-1] = new_plane;
}else{
pport->tail[action-1]->next = new_plane;
pport->tail[action-1] = new_plane;
}
pport->current_plane_noes[action-1] = pport->current_plane_noes[action-1] + 2;
pport->counts[action-1] = pport->counts[action-1] + 1;
pport->accu_counts[action-1] = pport->accu_counts[action-1] + 1;
return new_plane;
}
/*연료소진 등으로 비상 착륙해야 할 비행기를 일반 활주로의 선두에 넣음*/
P_PLANE AddToPortHead(P_PORT pport,P_PLANE plane,int time_arrive)
{
P_PLANE temp;
if(plane==NULL /*|| pport->counts[plane->action-1]>=pport->max_plane_count*/) return NULL;
plane->port->plane_count_goto_another_port = plane->port->plane_count_goto_another_port + 1;
pport->plane_count_from_another_port = pport->plane_count_from_another_port + 1;
temp = pport->head[plane->action-1];
pport->head[plane->action-1] = plane;
plane->next = temp;
if(NULL==temp){
pport->tail[plane->action-1]=plane;
pport->tail[plane->action-1]->next = NULL;
}
plane->time_arrive = time_arrive;
plane->time_can_wait_from_arrive = 0;
plane->port = pport;
pport->counts[plane->action-1] = pport->counts[plane->action-1] + 1;
pport->accu_counts[plane->action-1] = pport->accu_counts[plane->action-1] + 1;
return plane;
}
/*연료소진 등으로 비상 착륙해야 할 비행기를 비상활주로의 끝에 넣음*/
P_PLANE AddToPortTail(P_PORT pport,P_PLANE plane,int time_arrive)
{
P_PLANE temp;
if(plane==NULL /*|| pport->counts[plane->action-1]>=pport->max_plane_count*/) return NULL;
plane->port->plane_count_goto_another_port = plane->port->plane_count_goto_another_port + 1;
pport->plane_count_from_another_port = pport->plane_count_from_another_port + 1;
plane->next = NULL;
if(pport->head[plane->action-1]==NULL){
pport->head[plane->action-1] = plane;
pport->tail[plane->action-1] = plane;
}else{
pport->tail[plane->action-1]->next = plane;
pport->tail[plane->action-1] = plane;
}
plane->time_arrive = time_arrive;
plane->time_can_wait_from_arrive = 0;
plane->port = pport;
pport->counts[plane->action-1] = pport->counts[plane->action-1] + 1;
pport->accu_counts[plane->action-1] = pport->accu_counts[plane->action-1] + 1;
return plane;
}
P_PLANE RemoveFromPort(P_PORT pport,PLANEACTION action,int current_time)
{
P_PLANE plane = pport->head[action-1];
if(plane==NULL) return NULL;
pport->head[action-1] = pport->head[action-1]->next;
pport->counts[action-1] = pport->counts[action-1] - 1;
pport->accu_time_waits[action-1] = pport->accu_time_waits[action-1] + current_time - plane->time_arrive;
if(NULL==pport->head[action-1]){
pport->tail[action-1]=NULL;
}
return plane;
}
int HasThisPlane(P_PORT pport,P_PLANE plane)
{
P_PLANE cur=pport->head[plane->action-1];
while(cur){
if(cur==plane) return 1;
cur = cur->next;
}
return 0;
}
P_PLANE SearchPrevPlane(P_PORT pport,P_PLANE plane)
{
P_PLANE prev=NULL,cur=pport->head[plane->action-1];
while(cur!=NULL){
if(cur==plane) return prev;
prev = cur;
cur = cur->next;
}
return NULL;
}
P_PLANE RemoveThisPlaneFromPort(P_PORT pport,P_PLANE plane,int current_time)
{
P_PLANE prev_plane;
if(plane==NULL) return NULL;
if(plane==pport->head[plane->action-1]) return RemoveFromPort(pport,plane->action,current_time);
prev_plane = SearchPrevPlane(pport,plane);
/*head도 아닌데 앞 비행기가 없다면 이 활주로에 할당된 비행기가 아님*/
if(prev_plane==NULL) return NULL;
prev_plane->next = plane->next;
if(pport->tail[plane->action-1]==plane) pport->tail[plane->action-1] = prev_plane;
pport->counts[plane->action-1] = pport->counts[plane->action-1] - 1;
pport->accu_time_waits[plane->action-1] = pport->accu_time_waits[plane->action-1] + current_time - plane->time_arrive;
return plane;
}
void ResetPort(P_PORT pport)
{
P_PLANE temp,plane;
int i;
for(i=0 ;i<2 ;i=i+1){
plane=pport->head[i];
while(plane){
temp = plane;
plane = plane->next;
free(temp);
}
pport->head[i] = NULL;
pport->tail[i] = NULL;
pport->counts[i] = 0;
pport->accu_counts[i]=0;
pport->accu_time_waits[i] = 0;
pport->plane_count_from_another_port = 0;
pport->plane_count_goto_another_port = 0;
}
pport->time_wait_to_land = 0;
pport->usage = paClosed;
pport->action_to_take = paLand;
}
void CreatePorts(P_AIRPORT pairport,int max_plane_count,int reserved_port_no,PLANEACTION reserved_for_what)
{
int i,j;
pairport->ports = (P_PORT)malloc(sizeof(PORT)*pairport->port_count);
for(i=0 ;i<pairport->port_count ;i=i+1){
ResetPort(&pairport->ports[i]);
pairport->ports[i].no = i;
pairport->ports[i].max_plane_count = max_plane_count;
pairport->ports[i].usage = paLandTakeoff;
pairport->ports[i].time_to_land_from_arrive = pairport->time_to_land_from_arrive;
for(j=0 ;j<2 ;j=j+1){
pairport->ports[i].current_plane_noes[j] = (j+1)%2;
}
}
pairport->plane_count_of_cant_service=0;
if(pairport->reserved_port_no>=0 && pairport->reserved_port_no<pairport->port_count){
pairport->ports[pairport->reserved_port_no].usage = pairport->reserved_for_what;
}
}
void ResetPorts(P_AIRPORT pairport)
{
int i,j;
for(i=0 ;i<pairport->port_count ;i=i+1){
ResetPort(&pairport->ports[i]);
}
free(pairport->ports);
pairport->ports = NULL;
pairport->port_count = 0;
}
void PrintPortStatus(P_PORT pport,int current_time)
{
P_PLANE plane;
int i,wait_time,remain_wait_time,time_to_emergency;
int total_wait_times[2],total_emergencies[2];
fprintf(g_FP_LOG,"\\nPort%d\'s planes:",pport->no);
for(i=0 ;i<2 ;i=i+1){
total_wait_times[i] = 0;
total_emergencies[i] = 0;
plane = pport->head[i];
while(plane!=NULL){
wait_time = current_time-plane->time_arrive;
remain_wait_time = (plane->time_arrive+plane->time_to_land_from_arrive)-current_time;
time_to_emergency = plane->time_can_wait_from_arrive - wait_time;
fprintf(g_FP_LOG,"\\nNo:%3d[%s] Arrived_at:%4d Wait_time:%4d Remain_wait_time:%4d Time_to_emergency:%4d %s"
,plane->no
,PlaneActionLabels[plane->action]
,plane->time_arrive
,wait_time
,remain_wait_time
,time_to_emergency
,(time_to_emergency<=0?"Emergent":" ")
);
total_wait_times[i] = total_wait_times[i] + wait_time;
if(time_to_emergency<=0) total_emergencies[i] = total_emergencies[i] + 1;
plane = plane->next;
}
}
fprintf(g_FP_LOG,"\\nPort%d\'s Status Result:",pport->no);
fprintf(g_FP_LOG,"\\nPlanes waiting: %d",pport->counts[0]+pport->counts[1]);
fprintf(g_FP_LOG,"\\nPlanes wait to Land: %d",pport->counts[0]);
fprintf(g_FP_LOG,"\\nPlanes wait to Takeoff: %d",pport->counts[1]);
fprintf(g_FP_LOG,"\\nPlanes at Emergency: %d(%d+%d)",total_emergencies[0]+total_emergencies[1],total_emergencies[0],total_emergencies[1]);
fprintf(g_FP_LOG,"\\nPlanes from another port: %d",pport->plane_count_from_another_port);
fprintf(g_FP_LOG,"\\nPlanes goto another port: %d",pport->plane_count_goto_another_port);
fprintf(g_FP_LOG,"\\nPlanes Total: %d (%d+%d) ",pport->accu_counts[0]+pport->accu_counts[1],pport->accu_counts[0],pport->accu_counts[1]);
if(pport->accu_counts[0]>0)
fprintf(g_FP_LOG,"\\nTotal & Average wait time to Land: %d & %d"
,pport->accu_time_waits[0]
,(pport->accu_time_waits[0])/pport->accu_counts[0]);
if(pport->accu_counts[1]>0)
fprintf(g_FP_LOG,"\\nTotal & Average wait time to Takeoff: %d & %d"
,pport->accu_time_waits[1]
,(pport->accu_time_waits[1])/pport->accu_counts[1]);
fprintf(g_FP_LOG,"\\n");
}
void PrintAirportStatus(P_AIRPORT pairport,int current_time)
{
int i;
fprintf(g_FP_LOG,"\\n\\n*********** Airport Status(%d) ***********",current_time);
fprintf(g_FP_LOG,"\\nCannot Service: %d\\n",pairport->plane_count_of_cant_service);
for(i=0 ;i<pairport->port_count ;i=i+1){
PrintPortStatus(&pairport->ports[i],current_time);
fprintf(g_FP_LOG,"\\n");
}
}
댓글 영역
획득법
① NFT 발행
작성한 게시물을 NFT로 발행하면 일주일 동안 사용할 수 있습니다. (최초 1회)
② NFT 구매
다른 이용자의 NFT를 구매하면 한 달 동안 사용할 수 있습니다. (구매 시마다 갱신)
사용법
디시콘에서지갑연결시 바로 사용 가능합니다.