#include<iostream.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include<fstream.h>
ofstream f1("d:\\电梯问题.txt");
//-----------------------------------------------------------------------------------------
//初始定义
//-----------------------------------------------------------------------------------------
//----------------------------
//第一类,输入型
//----------------------------
double TimeIncludeStop=15.5; //停站过一层的时间
double TimeNoStop=7.56; //不停站过一层的时间
int NumOfLaysOfBuilding=30; //楼层数
double Lamda=2.427/6; //人数的总平均到达率,作为泊松分布参数
double StepTimeAverageArrivalPerson=36.405/6; //步长时间内平均到达人数
const int MaxPersonOfElevator=19; //电梯限载人数
double StepTime=15; //步长时间
int TimesOfCpu=160; //模拟次数
int NumOfGround=0; //电梯落地时间
double SumTimeOfInElevator=0; //人在电梯内的总时间,就是乘坐时间
double Q;
//----------------------------
//第一类结束
//----------------------------
//----------------------------
//第二类,初始化型
//----------------------------
double SumOfWaitingTime=0; //总等待时间
int SumOfNumOfPerson=0; //总人数
double LastTimeStopInOneLay=0; //上一次停靠在一楼的时间(初始化为零)
double CurrentTime=0; //当前时间(初始化为零) //每一次都需要更新
int TransportNumOfPerson=0; //电梯运输人数
int SumOfNumOfStop=0; //电梯的停靠次数
//----------------------------
//第二类结束
//----------------------------
//----------------------------
//其他类开始
//----------------------------
class PERSON
{
public:
int Destination; //目地楼层
int DelayTime; //个人延时
};
int CurrentNumOfPerson; //当前人数,就是堆栈中的人数
#define MaxOfTimesOfCpu 200 //最大模拟次数,暂时定位200
#define Inf 10000 //10000
int SaveP_Rand[MaxOfTimesOfCpu]; //产生200个随机数,用来初始化每一次产生人数
int SaveRand[Inf]; //产生随机数,用来初始化每个人的目的楼层
PERSON PersonGetInElevator[Inf];//就是进入电梯的人
int NumOfPersonGetInElevator=0;//进入电梯的人数
PERSON Person[MaxOfTimesOfCpu][Inf];
//
//----------------------------
//其他类结束
//----------------------------
//-----------------------------------------------------------------------------------------
//初始定义结束
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
//判断电梯到达函数,到达返回1,不到达返回0.
//-----------------------------------------------------------------------------------------
int ElevatorIsArrival(int i,PERSON PersonGetInElevator[Inf],double NumOfGetInElevator)//
{
double ElevatorWorkNeedTime=0;
//第一次模拟,电梯在一楼
if(i==0)
{
return 1;
}
//不是第一次模拟摇判断电梯是否在一楼
else
{
//-------------------------------------------------------
//过程:为啦求出电梯的ElevatorWorkNeedTime
//ElevatorWorkNeedTime=(最高楼层数-停靠的楼层数)*TimeNoStop+停靠的楼层数*TimeIncludeStop
//-------------------------------------------------------
//计算停靠的最高层代码开始
int HighestLay=PersonGetInElevator[0].Destination;
for(int j=0;j<NumOfPersonGetInElevator;j++)
{
if(PersonGetInElevator[j].Destination>HighestLay)
HighestLay=PersonGetInElevator[j].Destination;
}
//计算停靠的最高层代码结束
//计算停靠的次数代码开始
int NumOfStopLay=0;
for(j=0;j<NumOfGetInElevator;j++)
{
int LayAsSameAsBeforPerson=0;
for(int l=0;l<j;l++)
{
if(PersonGetInElevator[l].Destination==PersonGetInElevator[j].Destination)
{
LayAsSameAsBeforPerson=1;
break;
}
}
if(LayAsSameAsBeforPerson==0)
NumOfStopLay++;
}
//计算停靠的次数代码结束
ElevatorWorkNeedTime=(HighestLay-NumOfStopLay)*TimeNoStop
+NumOfStopLay*TimeIncludeStop+HighestLay*TimeNoStop;
if(CurrentTime-LastTimeStopInOneLay>=ElevatorWorkNeedTime)
return 1;
else
return 0;
}
}
//-----------------------------------------------------------------------------------------
//判断电梯到达函数结束
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
//产生随机数函数,其中包裹,随机数,均匀分布随机数和泊松分布随机数
//-----------------------------------------------------------------------------------------
#define random(x) (rand()%x)
int GernateRandom(double NumOfRandom,double Max_Random)//产生随机数NumOfRandom,
{
srand((int)time(0));
for(int i=0;i<NumOfRandom;i++)
{
SaveP_Rand[i]=random((int)Max_Random);
}
return 0;
}
int GernateRandom2(int NumOfRandom,int Max_Random)//产生随机数NumOfRandom,
{
srand((int)time(0));
for(int i=0;i<NumOfRandom;i++)
{
SaveRand[i]=random(Max_Random-1)+1;
}
return 0;
}
//产生符合均匀分布的函数
double U_Rand(double a,double b,double Max_U_Rand,double NumOfRandom) //均匀分布,Max_U_Rand是随机数的最大值
{
double x=GernateRandom(NumOfRandom,Max_U_Rand);
return a+(b-a)*x/(Max_U_Rand-1);
}
//产生符合泊松分布的函数
double P_Rand(double Lamda,double Max_P_Rand,double NumOfRandom)//泊松分布,Lamda为平局到达率,NumOfRandom为随机数的个数
{
double x=0,b=1,c=exp(-Lamda),u;
do{
u=U_Rand(0,1,Max_P_Rand,NumOfRandom);
b*=u;
if(b>=c)
x++;
}while(b>=c);
return x;
}
//-----------------------------------------------------------------------------------------
//产生随机数函数结束
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
//堆栈
//-----------------------------------------------------------------------------------------
#define QElemType PERSON
#define Status bool
//#define OVERFLOW 0
#define OK 1
#define ERROR 0
typedef struct QNode
{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
Status InitQueue(LinkQueue &Q)
{ //构造一个空队列Q
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front) exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
Status DestroyQueue(LinkQueue &Q)
{ //销毁队列
while(Q.front)
{
Q.rear=Q.front->next;
free(Q.front);
Q.front=Q.rear;
}
return OK;
}
Status EnQueue(LinkQueue &Q,QElemType e)
{
//插入元素e为Q新的队尾元素
QNode *p=(QueuePtr)malloc(sizeof(QNode));
if(!p) exit(OVERFLOW);
p->data=e; p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return OK;
}
Status DeQueue(LinkQueue &Q,QElemType &e)
{
//若队列不空,则删除Q的队头元素,用e放回气质,并返回OK
//否则返回ERROR
if(Q.front==Q.rear) return ERROR;
QNode *p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p) Q.rear=Q.front;
free(p);
return OK;
}
//-----------------------------------------------------------------------------------------
//堆栈代码结束
//-----------------------------------------------------------------------------------------
double Math_NumOfStop(int NumOfGetInElevator,PERSON PersonGetInElevator[Inf])
{
//定义一个数组,作为返回值,
//第一表示SumTimeOfInElevator,第二作为表示NumOfStop
int CurrentLay=0;//当前电梯的层数,注意,这里从零开始,因为用Index_ListOfStop控制最大值
int CurrentNumOfPersonInElevaltor=NumOfGetInElevator;//电梯上的当前人数,初始化为上电梯的人数
int Index_ListOfStop=-1;//最终表明电梯的最高层数,加1表示最高楼层数
int ListOfStop[Inf];//值表示目的地,就是楼层数
int ListOfDownPeople[Inf];//第一个数表示站,第二个数放到这个站的人的个数
//----------------------------------------------------------------------------------------
//电梯初期数据处理
//----------------------------------------------------------------------------------------
//过程开始存储目的楼层序列ListOfStop
for(int j=0;j<NumOfGetInElevator;j++)
{
int LayAsSameAsBeforPerson=0;//是否跟前面的相同
for(int l=0;l<j;l++)
{
//跟前面的目的楼层数相同,跳出循环,不用存储
if(PersonGetInElevator[l].Destination==PersonGetInElevator[j].Destination)
{
LayAsSameAsBeforPerson=1;
break;
}
}
//一直到底都跟前面目的楼层的不相同,就是说发现新的楼层数,存储
if(LayAsSameAsBeforPerson==0)
{
//首先数组键名增加一
Index_ListOfStop++;
//保存新发现的楼层目的地,保存在数组ListOfStop当中
ListOfStop[Index_ListOfStop]=PersonGetInElevator[j].Destination;
}
}
//存储目的楼层序列ListOfStop结束
return Index_ListOfStop++;
}
double Elevaltor(int NumOfGetInElevator,PERSON PersonGetInElevator[Inf])//传进来什么参数
{
double SumTimeOfInElevator=0;
double NumOfStop=0;
//定义一个数组,作为返回值,
//第一表示SumTimeOfInElevator,第二作为表示NumOfStop
int CurrentLay=0;//当前电梯的层数,注意,这里从零开始,因为用Index_ListOfStop控制最大值
int CurrentNumOfPersonInElevaltor=NumOfGetInElevator;//电梯上的当前人数,初始化为上电梯的人数
int Index_ListOfStop=-1;//最终表明电梯的最高层数,加1表示最高楼层数
int ListOfStop[Inf];//值表示目的地,就是楼层数
int ListOfDownPeople[Inf];//第一个数表示站,第二个数放到这个站的人的个数
//----------------------------------------------------------------------------------------
//电梯初期数据处理
//----------------------------------------------------------------------------------------
//过程开始存储目的楼层序列ListOfStop
for(int j=0;j<NumOfGetInElevator;j++)
{
int LayAsSameAsBeforPerson=0;//是否跟前面的相同
for(int l=0;l<j;l++)
{
//跟前面的目的楼层数相同,跳出循环,不用存储
if(PersonGetInElevator[l].Destination==PersonGetInElevator[j].Destination)
{
LayAsSameAsBeforPerson=1;
break;
}
}
//一直到底都跟前面目的楼层的不相同,就是说发现新的楼层数,存储
if(LayAsSameAsBeforPerson==0)
{
//首先数组键名增加一
Index_ListOfStop++;
//保存新发现的楼层目的地,保存在数组ListOfStop当中
ListOfStop[Index_ListOfStop]=PersonGetInElevator[j].Destination;
}
}
//存储目的楼层序列ListOfStop结束
//对目的楼层序列进行排序
for(j=0;j<=Index_ListOfStop;j++)
{
for(int i=0;i<j;i++)
{
if(ListOfStop[j]<ListOfStop[i])
{
int temp=ListOfStop[j];
ListOfStop[j]=ListOfStop[i];
ListOfStop[i]=temp;
}
}
}
//对目的楼层序列排序结束
//测试部分
/* for(int i=0;i<=Index_ListOfStop;i++)
{
cout<<ListOfStop[i]<<endl;
}*/
//测试部分
//对目的楼层到的人数进行处理
for(j=0;j<NumOfGetInElevator;j++)
{
ListOfDownPeople[j]=0;
}
for(j=0;j<NumOfGetInElevator;j++)
{
for(int i=0;i<=Index_ListOfStop;i++)
{
if(PersonGetInElevator[j].Destination==ListOfStop[i])
{
ListOfDownPeople[i]++;
}
}
}
/* for(j=0;j<=Index_ListOfStop;j++)
{
cout<<ListOfDownPeople[j]<<endl;
}*/
//----------------------------------------------------------------------------------------
//电梯初期数据处理
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//电梯开始飞
//----------------------------------------------------------------------------------------
//求平均乘坐时间
for(CurrentLay=0;CurrentLay<=ListOfStop[Index_ListOfStop];CurrentLay++)
{
//判断是否有人下电梯,如果有人下电梯,为1
//同时产生一个IndexStopOfDownPerson表明第几个停靠点
int IsDownPerson=0;
int IndexStopOfDownPerson;
for(int i=0;i<=Index_ListOfStop;i++)
{
if(CurrentLay==ListOfStop[i])
{
IsDownPerson=1;
IndexStopOfDownPerson=i;
break;
}
}
if(IsDownPerson)
{
//更新当前人数,当前人数等于前一个当前人数减去下去的人数
CurrentNumOfPersonInElevaltor-=ListOfDownPeople[IndexStopOfDownPerson];
//更新时间//乘坐时间+=当前人数*TimeIncludeStop
SumTimeOfInElevator+=CurrentNumOfPersonInElevaltor*TimeIncludeStop;
printf("\n");
printf(" | 在%d层下%d人\n",CurrentLay+1,ListOfDownPeople[IndexStopOfDownPerson]);
printf(" | 当前电梯内人数%d\n",CurrentNumOfPersonInElevaltor);
printf(" *|* 当前乘坐总时间%f\n",SumTimeOfInElevator);
printf("\n");
f1<<endl;
f1<<" | 在"<<CurrentLay+1<<"层下"<<ListOfDownPeople[IndexStopOfDownPerson]<<"人"<<endl;
f1<<" | 在前电梯内人数"<<CurrentNumOfPersonInElevaltor<<endl;
f1<<" *|* 当前乘坐总时间"<<SumTimeOfInElevator<<endl;
f1<<endl;
}
else
{
//当前人数不用更新,因为没有人下车
//更新时间//shijian+=当前人数*TimeNoStop
SumTimeOfInElevator+=CurrentNumOfPersonInElevaltor*TimeIncludeStop;
printf("\n");
printf(" | 在%d层没有停,没有下人\n",CurrentLay+1);
printf(" | 当前电梯内人数%d\n",CurrentNumOfPersonInElevaltor);
printf(" | 当前乘坐总时间%f\n",SumTimeOfInElevator);
printf("\n");
cout<<endl;
f1<<" | 在"<<CurrentLay+1<<"层没有停,没有下人"<<endl;
f1<<" | 当前电梯内人数"<<CurrentNumOfPersonInElevaltor<<endl;
f1<<" | 当前乘坐总时间"<<SumTimeOfInElevator<<endl;
cout<<endl;
}
}
return SumTimeOfInElevator;
}
int main()
{
LinkQueue Q;//定义队列
InitQueue(Q);//初始化队列
P_Rand(Lamda,2*StepTimeAverageArrivalPerson,TimesOfCpu);//产生人数让后用SaveP_Rand[]保存
for(int i=0;i<TimesOfCpu;i++)
{
//------------------------------------------------------------------------------
//第i次模拟初始化开始
//------------------------------------------------------------------------------
//生成的人进栈;
int NumOfPerson=SaveP_Rand[i];//产生每一次的人
SumOfNumOfPerson+=NumOfPerson;//更新总人数
GernateRandom2(NumOfPerson,NumOfLaysOfBuilding);//产生NumOfPerson组随机数,用来初始化么个人的楼层
for(int j=0;j<NumOfPerson;j++)
{
Person[i][j].Destination=SaveRand[j];//产生第i次模拟的到达人的目的地
}
CurrentTime+=StepTime;//更新时间
CurrentNumOfPerson+=NumOfPerson;//更新队列内人数
//生成的人进栈,然后如果电梯到来那么再出战。所以当前时间不能再这个地方算
for(j=0;j<NumOfPerson;j++)
{
EnQueue(Q,Person[i][j]);
}
//生成的人进栈结束
//------------------------------------------------------------------------------
//第i次模拟初始化结束
//------------------------------------------------------------------------------
if(ElevatorIsArrival(i,PersonGetInElevator,NumOfPersonGetInElevator))
{
NumOfGround++;
//检测部分++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cout<<"************"<<endl;
cout<<"**电梯到达*******************************"<<endl;
cout<<"************"<<endl;
f1<<"************"<<endl;
f1<<"**电梯到达********************************"<<endl;
f1<<"************"<<endl;
//检测部分++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//更新电梯上一次到达时间
LastTimeStopInOneLay=CurrentTime;
if(CurrentNumOfPerson<MaxPersonOfElevator)//队列内的人数小于电梯内最大载人数
{
//把队列中的元素清空
NumOfPersonGetInElevator=0;//把以前电梯中的人数清零,让后累加出来
for(int l=0;Q.front!=Q.rear;l++)
{
//把每一次进电梯的人都从队列删除,同时保存起来给PersonGetInElevator[]
QElemType e;
DeQueue(Q,e);
PersonGetInElevator[l].DelayTime=e.DelayTime;
PersonGetInElevator[l].Destination=e.Destination;
NumOfPersonGetInElevator++;//进入电梯中,电梯中人数累加
}
//计算等待时间因为队列的人数小于电梯内的总人数,所以没有等待时间的更新
//因为上了电梯就一定能运输到地方,所以运输人数就是上电梯人数
TransportNumOfPerson+=NumOfPersonGetInElevator;
//更新在电梯内的总人数
SumTimeOfInElevator+=Elevaltor(NumOfPersonGetInElevator,PersonGetInElevator);
//更新电梯的总停靠次数
SumOfNumOfStop++;
SumOfNumOfStop+=Math_NumOfStop(NumOfPersonGetInElevator,PersonGetInElevator);
}
else
{
//出栈队列中的MaxPersonOfElevator个元素,同时保存给PersonGetInElevator[]
int temp=MaxPersonOfElevator;
for(int l=0;temp>0;temp--&&l++)
{
QElemType e;
DeQueue(Q,e);
PersonGetInElevator[l].DelayTime=e.DelayTime;
PersonGetInElevator[l].Destination=e.Destination;
}
//更新电梯人数
NumOfPersonGetInElevator=MaxPersonOfElevator;
//更新堆栈中人数
CurrentNumOfPerson-=MaxPersonOfElevator;
//总等待时间
SumOfWaitingTime+=CurrentNumOfPerson*StepTime;
//更新运输人数
TransportNumOfPerson+=NumOfPersonGetInElevator;
//更新电梯中的总人数
SumTimeOfInElevator+=Elevaltor(NumOfPersonGetInElevator,PersonGetInElevator);
//更新电梯的停靠次数
SumOfNumOfStop++;
SumOfNumOfStop+=Math_NumOfStop(NumOfPersonGetInElevator,PersonGetInElevator);
}
}
else//就是电梯没有到达,堆栈中的人数已经进栈,并且数目已经更新,这里不用再更新
{
//检测部分++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cout<<"****************"<<endl;
cout<<"**让电梯飞一会**"<<endl;
cout<<"****************"<<endl;
f1<<"****************"<<endl;
f1<<"**让电梯飞一会**"<<endl;
f1<<"****************"<<endl;
//检测部分++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//总的等待时间+=堆栈中当前人数*StepTime;
SumOfWaitingTime+=CurrentNumOfPerson*StepTime;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//检测准备输出各种数据,因为等待时间,堆栈当前人数,
//等等都在这个时候更新完成
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cout<<"第"<<i<<"次模拟"<<endl;
cout<<"新来人数"<<NumOfPerson<<endl;
cout<<"当前总人数"<<SumOfNumOfPerson<<endl;
cout<<"当前总等待时间"<<SumOfWaitingTime<<endl;
cout<<"当前时间"<<CurrentTime<<endl;
cout<<"运输人数"<<TransportNumOfPerson<<endl;
cout<<"电梯停靠次数"<<SumOfNumOfStop<<endl;
cout<<endl;
cout<<endl;
f1<<"第"<<i<<"次模拟"<<endl;
f1<<"新来人数"<<NumOfPerson<<endl;
f1<<"当前总人数"<<SumOfNumOfPerson<<endl;
f1<<"当前总等待时间"<<SumOfWaitingTime<<endl;
f1<<"当前时间"<<CurrentTime<<endl;
f1<<"运输人数"<<TransportNumOfPerson<<endl;
f1<<"电梯停靠次数"<<SumOfNumOfStop<<endl;
f1<<endl;
f1<<endl;
}
// Elevaltor(NumOfPersonGetInElevator,PersonGetInElevator,SumTimeOfInElevator);
//(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
//模拟结束开准备输出结果
//(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
cout<<"总等待时间"<<SumOfWaitingTime<<endl;
cout<<"总到达人数"<<SumOfNumOfPerson<<endl;
cout<<"运输人数能力"<<TransportNumOfPerson<<endl;
cout<<"总乘坐时间"<<SumTimeOfInElevator<<endl;
cout<<"电梯落地时间"<<NumOfGround<<endl;
f1<<"总等待时间"<<SumOfWaitingTime<<endl;
f1<<"运输人数能力"<<TransportNumOfPerson<<endl;
f1<<"总乘坐时间"<<SumTimeOfInElevator<<endl;
f1<<"电梯落地次数"<<endl;
//))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
//第i次模拟的初始化结束
//))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
f1.close;
return 0;
}
数学建模时候的蒙特卡洛模拟
最新推荐文章于 2023-05-16 22:26:18 发布