数学建模时候的蒙特卡洛模拟

来源:互联网 发布:python爬虫赚钱收入 编辑:程序博客网 时间:2024/05/01 03:59
#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         //10000int 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;elsereturn 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     0typedef struct QNode{ QElemType data;struct QNode   *next;}QNode,*QueuePtr;typedef struct{QueuePtr front;QueuePtr rear;}LinkQueue;Status InitQueue(LinkQueue &Q){   //构造一个空队列QQ.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//否则返回ERRORif(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,第二作为表示NumOfStopint CurrentLay=0;//当前电梯的层数,注意,这里从零开始,因为用Index_ListOfStop控制最大值int CurrentNumOfPersonInElevaltor=NumOfGetInElevator;//电梯上的当前人数,初始化为上电梯的人数int Index_ListOfStop=-1;//最终表明电梯的最高层数,加1表示最高楼层数int ListOfStop[Inf];//值表示目的地,就是楼层数int ListOfDownPeople[Inf];//第一个数表示站,第二个数放到这个站的人的个数//----------------------------------------------------------------------------------------//电梯初期数据处理//----------------------------------------------------------------------------------------//过程开始存储目的楼层序列ListOfStopfor(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,第二作为表示NumOfStopint CurrentLay=0;//当前电梯的层数,注意,这里从零开始,因为用Index_ListOfStop控制最大值int CurrentNumOfPersonInElevaltor=NumOfGetInElevator;//电梯上的当前人数,初始化为上电梯的人数int Index_ListOfStop=-1;//最终表明电梯的最高层数,加1表示最高楼层数int ListOfStop[Inf];//值表示目的地,就是楼层数int ListOfDownPeople[Inf];//第一个数表示站,第二个数放到这个站的人的个数//----------------------------------------------------------------------------------------//电梯初期数据处理//----------------------------------------------------------------------------------------//过程开始存储目的楼层序列ListOfStopfor(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];//更新时间//乘坐时间+=当前人数*TimeIncludeStopSumTimeOfInElevator+=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+=当前人数*TimeNoStopSumTimeOfInElevator+=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;}

原创粉丝点击