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

#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;
}



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值